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 ];
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;
74 /* get the home environment variable */
75 home = getenv( "HOME" );
77 return Q_strncpyz( buf, home, sizeof( buf ) );
80 /* look up home dir in password database */
81 if ( getpwuid_r( getuid(), &pw, buf, sizeof( buf ), &pwp ) == 0 ) {
93 initializes some paths on linux/os x
96 void LokiInitPaths( char *argv0 ){
98 /* this is kinda crap, but hey */
99 strcpy( installPath, "../" );
101 char temp[ MAX_OS_PATH ];
109 home = LokiGetHomeDir();
110 if ( home == NULL ) {
114 /* do some path divining */
115 strcpy( temp, argv0 );
116 if ( strrchr( temp, '/' ) ) {
117 argv0 = strrchr( argv0, '/' ) + 1;
121 /* get path environment variable */
122 path = getenv( "PATH" );
125 last[ 0 ] = path[ 0 ];
129 /* go through each : segment of path */
130 while ( last[ 0 ] != '\0' && found == qfalse )
135 /* find next chunk */
136 last = strchr( path, ':' );
137 if ( last == NULL ) {
138 last = path + strlen( path );
141 /* found home dir candidate */
142 if ( *path == '~' ) {
143 strcpy( temp, home );
148 if ( last > ( path + 1 ) ) {
149 strncat( temp, path, ( last - path ) );
152 strcat( temp, "./" );
153 strcat( temp, argv0 );
155 /* verify the path */
156 if ( access( temp, X_OK ) == 0 ) {
164 if ( realpath( temp, installPath ) ) {
165 /* q3map is in "tools/" */
166 *( strrchr( installPath, '/' ) ) = '\0';
167 *( strrchr( installPath, '/' ) + 1 ) = '\0';
179 cleans a dos path \ -> /
182 void CleanPath( char *path ){
185 if ( *path == '\\' ) {
196 gets the game_t based on a -game argument
197 returns NULL if no match found
200 game_t *GetGame( char *arg ){
205 if ( arg == NULL || arg[ 0 ] == '\0' ) {
210 if ( !Q_stricmp( arg, "quake1" ) ||
211 !Q_stricmp( arg, "quake2" ) ||
212 !Q_stricmp( arg, "unreal" ) ||
213 !Q_stricmp( arg, "ut2k3" ) ||
214 !Q_stricmp( arg, "dn3d" ) ||
215 !Q_stricmp( arg, "dnf" ) ||
216 !Q_stricmp( arg, "hl" ) ) {
217 Sys_Printf( "April fools, silly rabbit!\n" );
223 while ( games[ i ].arg != NULL )
225 if ( Q_stricmp( arg, games[ i ].arg ) == 0 ) {
231 /* no matching game */
238 AddBasePath() - ydnar
239 adds a base path to the list
242 void AddBasePath( char *path ){
244 if ( path == NULL || path[ 0 ] == '\0' || numBasePaths >= MAX_BASE_PATHS ) {
248 /* add it to the list */
249 basePaths[ numBasePaths ] = safe_malloc( strlen( path ) + 1 );
250 strcpy( basePaths[ numBasePaths ], path );
251 CleanPath( basePaths[ numBasePaths ] );
258 AddHomeBasePath() - ydnar
259 adds a base path to the beginning of the list, prefixed by ~/
262 void AddHomeBasePath( char *path ){
265 char temp[ MAX_OS_PATH ];
269 if ( path == NULL || path[ 0 ] == '\0' ) {
274 for ( i = 0; i < ( MAX_BASE_PATHS - 1 ); i++ )
275 basePaths[ i + 1 ] = basePaths[ i ];
277 /* concatenate home dir and path */
278 sprintf( temp, "%s/%s", homePath, path );
280 /* add it to the list */
281 basePaths[ 0 ] = safe_malloc( strlen( temp ) + 1 );
282 strcpy( basePaths[ 0 ], temp );
283 CleanPath( basePaths[ 0 ] );
291 AddGamePath() - ydnar
292 adds a game path to the list
295 void AddGamePath( char *path ){
299 if ( path == NULL || path[ 0 ] == '\0' || numGamePaths >= MAX_GAME_PATHS ) {
303 /* add it to the list */
304 gamePaths[ numGamePaths ] = safe_malloc( strlen( path ) + 1 );
305 strcpy( gamePaths[ numGamePaths ], path );
306 CleanPath( gamePaths[ numGamePaths ] );
309 /* don't add it if it's already there */
310 for ( i = 0; i < numGamePaths - 1; i++ )
312 if ( strcmp( gamePaths[i], gamePaths[numGamePaths - 1] ) == 0 ) {
313 free( gamePaths[numGamePaths - 1] );
314 gamePaths[numGamePaths - 1] = NULL;
327 cleaned up some of the path initialization code from bsp.c
328 will remove any arguments it uses
331 void InitPaths( int *argc, char **argv ){
332 int i, j, k, len, len2;
333 char temp[ MAX_OS_PATH ];
337 Sys_FPrintf( SYS_VRB, "--- InitPaths ---\n" );
339 /* get the install path for backup */
340 LokiInitPaths( argv[ 0 ] );
342 /* set game to default (q3a) */
347 /* parse through the arguments and extract those relevant to paths */
348 for ( i = 0; i < *argc; i++ )
351 if ( argv[ i ] == NULL ) {
356 if ( strcmp( argv[ i ], "-game" ) == 0 ) {
357 if ( ++i >= *argc ) {
358 Error( "Out of arguments: No game specified after %s", argv[ i - 1 ] );
360 argv[ i - 1 ] = NULL;
361 game = GetGame( argv[ i ] );
362 if ( game == NULL ) {
369 else if ( strcmp( argv[ i ], "-fs_basepath" ) == 0 ) {
370 if ( ++i >= *argc ) {
371 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
373 argv[ i - 1 ] = NULL;
374 AddBasePath( argv[ i ] );
379 else if ( strcmp( argv[ i ], "-fs_game" ) == 0 ) {
380 if ( ++i >= *argc ) {
381 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
383 argv[ i - 1 ] = NULL;
384 AddGamePath( argv[ i ] );
389 /* remove processed arguments */
390 for ( i = 0, j = 0, k = 0; i < *argc && j < *argc; i++, j++ )
392 for ( ; j < *argc && argv[ j ] == NULL; j++ ) ;
393 argv[ i ] = argv[ j ];
394 if ( argv[ i ] != NULL ) {
400 /* add standard game path */
401 AddGamePath( game->gamePath );
403 /* if there is no base path set, figure it out */
404 if ( numBasePaths == 0 ) {
405 /* this is another crappy replacement for SetQdirFromPath() */
406 len2 = strlen( game->magic );
407 for ( i = 0; i < *argc && numBasePaths == 0; i++ )
409 /* extract the arg */
410 strcpy( temp, argv[ i ] );
412 len = strlen( temp );
413 Sys_FPrintf( SYS_VRB, "Searching for \"%s\" in \"%s\" (%d)...\n", game->magic, temp, i );
415 /* this is slow, but only done once */
416 for ( j = 0; j < ( len - len2 ); j++ )
418 /* check for the game's magic word */
419 if ( Q_strncasecmp( &temp[ j ], game->magic, len2 ) == 0 ) {
420 /* now find the next slash and nuke everything after it */
421 while ( temp[ ++j ] != '/' && temp[ j ] != '\0' ) ;
424 /* add this as a base path */
431 /* add install path */
432 if ( numBasePaths == 0 ) {
433 AddBasePath( installPath );
437 if ( numBasePaths == 0 ) {
438 Error( "Failed to find a valid base path." );
442 /* this only affects unix */
443 AddHomeBasePath( game->homeBasePath );
445 /* initialize vfs paths */
446 if ( numBasePaths > MAX_BASE_PATHS ) {
447 numBasePaths = MAX_BASE_PATHS;
449 if ( numGamePaths > MAX_GAME_PATHS ) {
450 numGamePaths = MAX_GAME_PATHS;
453 /* walk the list of game paths */
454 for ( j = 0; j < numGamePaths; j++ )
456 /* walk the list of base paths */
457 for ( i = 0; i < numBasePaths; i++ )
459 /* create a full path and initialize it */
460 sprintf( temp, "%s/%s/", basePaths[ i ], gamePaths[ j ] );
461 vfsInitDirectory( temp );