fix compile errors
[divverent/netradiant.git] / tools / quake3 / q3map2 / path_init.c
1 /* -------------------------------------------------------------------------------
2
3 Copyright (C) 1999-2007 id Software, Inc. and contributors.
4 For a list of contributors, see the accompanying CONTRIBUTORS file.
5
6 This file is part of GtkRadiant.
7
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.
12
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.
17
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
21
22 ----------------------------------------------------------------------------------
23
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."
26
27 ------------------------------------------------------------------------------- */
28
29
30
31 /* marker */
32 #define PATH_INIT_C
33
34
35
36 /* dependencies */
37 #include "q3map2.h"
38
39
40
41 /* path support */
42 #define MAX_BASE_PATHS  10
43 #define MAX_GAME_PATHS  10
44
45 char                                    *homePath;
46 char                                    installPath[ MAX_OS_PATH ];
47
48 int                                             numBasePaths;
49 char                                    *basePaths[ MAX_BASE_PATHS ];
50 int                                             numGamePaths;
51 char                                    *gamePaths[ MAX_GAME_PATHS ];
52 char                                    *homeBasePath = NULL;
53
54
55 /*
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.
58 */
59
60 /*
61 PathLokiGetHomeDir()
62 gets the user's home dir (for ~/.q3a)
63 */
64
65 char *LokiGetHomeDir(void)
66 {
67         #ifndef Q_UNIX
68                 return NULL;
69         #else
70                 char                    *home;
71                 uid_t                   id;
72                 struct passwd   *pwd;
73                 static char homeBuf[MAX_OS_PATH];
74                 
75                 
76                 /* get the home environment variable */
77                 home = getenv( "HOME" );
78                 if( home == NULL )
79                 {
80                         /* do some more digging */
81                         id = getuid();
82                         setpwent();
83                         while( (pwd = getpwent()) != NULL )
84                         {
85                                 if( pwd->pw_uid == id )
86                                 {
87                                         home = pwd->pw_dir;
88                                         break;
89                                 }
90                         }
91                         endpwent();
92                 }
93
94                 snprintf(homeBuf, sizeof(homeBuf), "%s/.", home);
95                 
96                 /* return it */
97                 return homeBuf;
98         #endif
99 }
100
101
102
103 /*
104 PathLokiInitPaths()
105 initializes some paths on linux/os x
106 */
107
108 void LokiInitPaths( char *argv0 )
109 {
110         char            *home;
111
112         if(!homePath)
113         {
114                 /* get home dir */
115                 home = LokiGetHomeDir();
116                 if( home == NULL )
117                         home = ".";
118
119                 /* set home path */
120                 homePath = home;
121         }
122         else
123                 home = homePath;
124
125         #ifndef Q_UNIX
126                 /* this is kinda crap, but hey */
127                 strcpy( installPath, "../" );
128         #else
129                 char            temp[ MAX_OS_PATH ];
130                 char            last0[ 2 ];
131                 char            *path;
132                 char            *last;
133                 qboolean        found;
134                 
135                 
136                 /* do some path divining */
137                 strcpy( temp, argv0 );
138                 if( strrchr( argv0, '/' ) )
139                         argv0 = strrchr( argv0, '/' ) + 1;
140                 else
141                 {
142                         /* get path environment variable */
143                         path = getenv( "PATH" );
144                         
145                         /* minor setup */
146                         last = last0;
147                         last[ 0 ] = path[ 0 ];
148                         last[ 1 ] = '\0';
149                         found = qfalse;
150                         
151                         /* go through each : segment of path */
152                         while( last[ 0 ] != '\0' && found == qfalse )
153                         {
154                                 /* null out temp */
155                                 temp[ 0 ] = '\0';
156                                 
157                                 /* find next chunk */
158                                 last = strchr( path, ':' );
159                                 if( last == NULL )
160                                         last = path + strlen( path );
161                                 
162                                 /* found home dir candidate */
163                                 if( *path == '~' )
164                                 {
165                                         strcpy( temp, home );
166                                         path++;
167                                 }
168                                 
169                                 /* concatenate */
170                                 if( last > (path + 1) )
171                                 {
172                                         strncat( temp, path, (last - path) );
173                                         strcat( temp, "/" );
174                                 }
175                                 strcat( temp, "./" );
176                                 strcat( temp, argv0 );
177                                 
178                                 /* verify the path */
179                                 if( access( temp, X_OK ) == 0 )
180                                         found++;
181                                 path = last + 1;
182                         }
183                 }
184                 
185                 /* flake */
186                 if( realpath( temp, installPath ) )
187                 {
188                         /* q3map is in "tools/" */
189                         *(strrchr( installPath, '/' )) = '\0';
190                         *(strrchr( installPath, '/' ) + 1) = '\0';
191                 }
192         #endif
193 }
194
195
196
197 /*
198 CleanPath() - ydnar
199 cleans a dos path \ -> /
200 */
201
202 void CleanPath( char *path )
203 {
204         while( *path )
205         {
206                 if( *path == '\\' )
207                         *path = '/';
208                 path++;
209         }
210 }
211
212
213
214 /*
215 GetGame() - ydnar
216 gets the game_t based on a -game argument
217 returns NULL if no match found
218 */
219
220 game_t *GetGame( char *arg )
221 {
222         int     i;
223         
224         
225         /* dummy check */
226         if( arg == NULL || arg[ 0 ] == '\0' )
227                 return NULL;
228         
229         /* joke */
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" ) )
237         {
238                 Sys_Printf( "April fools, silly rabbit!\n" );
239                 exit( 0 );
240         }
241         
242         /* test it */
243         i = 0;
244         while( games[ i ].arg != NULL )
245         {
246                 if( Q_stricmp( arg, games[ i ].arg ) == 0 )
247                         return &games[ i ];
248                 i++;
249         }
250         
251         /* no matching game */
252         return NULL;
253 }
254
255
256
257 /*
258 AddBasePath() - ydnar
259 adds a base path to the list
260 */
261
262 void AddBasePath( char *path )
263 {
264         /* dummy check */
265         if( path == NULL || path[ 0 ] == '\0' || numBasePaths >= MAX_BASE_PATHS )
266                 return;
267         
268         /* add it to the list */
269         basePaths[ numBasePaths ] = safe_malloc( strlen( path ) + 1 );
270         strcpy( basePaths[ numBasePaths ], path );
271         CleanPath( basePaths[ numBasePaths ] );
272         numBasePaths++;
273 }
274
275
276
277 /*
278 AddHomeBasePath() - ydnar
279 adds a base path to the beginning of the list, prefixed by ~/
280 */
281
282 void AddHomeBasePath( char *path )
283 {
284         int             i;
285         char    temp[ MAX_OS_PATH ];
286         int homePathLen;
287         
288         if(!homePath)
289                 return;
290         
291         /* dummy check */
292         if( path == NULL || path[ 0 ] == '\0' )
293                 return;
294
295         /* strip leading dot, if homePath does not end in /. */
296         homePathLen = strlen(homePath);
297         if(!strcmp(path, "."))
298         {
299                 /* -fs_homebase . means that -fs_home is to be used as is */
300                 strcpy(temp, homePath);
301         }
302         else if(homePathLen >= 2 && !strcmp(homePath + homePathLen - 2, "/."))
303         {
304                 /* remove trailing /. of homePath */
305                 homePathLen -= 2;
306
307                 /* concatenate home dir and path */
308                 sprintf( temp, "%.*s/%s", homePathLen, homePath, path );
309         }
310         else
311         {
312                 /* remove leading . of path */
313                 if(path[0] == '.')
314                         ++path;
315
316                 /* concatenate home dir and path */
317                 sprintf( temp, "%s/%s", homePath, path );
318         }
319         
320         /* make a hole */
321         for( i = (MAX_BASE_PATHS - 2); i >= 0; i-- )
322                 basePaths[ i + 1 ] = basePaths[ i ];
323         
324         /* add it to the list */
325         basePaths[ 0 ] = safe_malloc( strlen( temp ) + 1 );
326         strcpy( basePaths[ 0 ], temp );
327         CleanPath( basePaths[ 0 ] );
328         numBasePaths++;
329 }
330
331
332
333 /*
334 AddGamePath() - ydnar
335 adds a game path to the list
336 */
337
338 void AddGamePath( char *path )
339 {
340         int     i;
341
342         /* dummy check */
343         if( path == NULL || path[ 0 ] == '\0' || numGamePaths >= MAX_GAME_PATHS )
344                 return;
345         
346         /* add it to the list */
347         gamePaths[ numGamePaths ] = safe_malloc( strlen( path ) + 1 );
348         strcpy( gamePaths[ numGamePaths ], path );
349         CleanPath( gamePaths[ numGamePaths ] );
350         numGamePaths++;
351
352         /* don't add it if it's already there */
353         for (i = 0; i < numGamePaths - 1; i++)
354         {
355                 if (strcmp(gamePaths[i], gamePaths[numGamePaths - 1]) == 0)
356                 {
357                         free(gamePaths[numGamePaths - 1]);
358                         gamePaths[numGamePaths - 1] = NULL;
359                         numGamePaths--;
360                         break;
361                 }
362         }
363         
364 }
365
366
367
368
369 /*
370 InitPaths() - ydnar
371 cleaned up some of the path initialization code from bsp.c
372 will remove any arguments it uses
373 */
374
375 void InitPaths( int *argc, char **argv )
376 {
377         int             i, j, k, len, len2;
378         char    temp[ MAX_OS_PATH ];
379         
380         
381         /* note it */
382         Sys_FPrintf( SYS_VRB, "--- InitPaths ---\n" );
383         
384         /* get the install path for backup */
385         LokiInitPaths( argv[ 0 ] );
386         
387         /* set game to default (q3a) */
388         game = &games[ 0 ];
389         numBasePaths = 0;
390         numGamePaths = 0;
391         
392         /* parse through the arguments and extract those relevant to paths */
393         for( i = 0; i < *argc; i++ )
394         {
395                 /* check for null */
396                 if( argv[ i ] == NULL )
397                         continue;
398                 
399                 /* -game */
400                 if( strcmp( argv[ i ], "-game" ) == 0 )
401                 {
402                         if( ++i >= *argc )
403                                 Error( "Out of arguments: No game specified after %s", argv[ i - 1 ] );
404                         argv[ i - 1 ] = NULL;
405                         game = GetGame( argv[ i ] );
406                         if( game == NULL )
407                                 game = &games[ 0 ];
408                         argv[ i ] = NULL;
409                 }
410
411                 /* -fs_forbiddenpath */
412                 else if( strcmp( argv[ i ], "-fs_forbiddenpath" ) == 0 )
413                 {
414                         if( ++i >= *argc )
415                                 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
416                         argv[ i - 1 ] = NULL;
417                         if(g_numForbiddenDirs < VFS_MAXDIRS)
418                         {
419                                 strncpy(g_strForbiddenDirs[g_numForbiddenDirs], argv[i], PATH_MAX);
420                                 g_strForbiddenDirs[g_numForbiddenDirs][PATH_MAX] = 0;
421                                 ++g_numForbiddenDirs;
422                         }
423                         argv[ i ] = NULL;
424                 }
425
426                 /* -fs_basepath */
427                 else if( strcmp( argv[ i ], "-fs_basepath" ) == 0 )
428                 {
429                         if( ++i >= *argc )
430                                 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
431                         argv[ i - 1 ] = NULL;
432                         AddBasePath( argv[ i ] );
433                         argv[ i ] = NULL;
434                 }
435                 
436                 /* -fs_game */
437                 else if( strcmp( argv[ i ], "-fs_game" ) == 0 )
438                 {
439                         if( ++i >= *argc )
440                                 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
441                         argv[ i - 1 ] = NULL;
442                         AddGamePath( argv[ i ] );
443                         argv[ i ] = NULL;
444                 }
445                 
446                 /* -fs_home */
447                 else if( strcmp( argv[ i ], "-fs_home" ) == 0 )
448                 {
449                         if( ++i >= *argc )
450                                 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
451                         argv[ i - 1 ] = NULL;
452                         homePath = argv[i];
453                         argv[ i ] = NULL;
454                 }
455                 
456                 /* -fs_homebase */
457                 else if( strcmp( argv[ i ], "-fs_homebase" ) == 0 )
458                 {
459                         if( ++i >= *argc )
460                                 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
461                         argv[ i - 1 ] = NULL;
462                         homeBasePath = argv[i];
463                         argv[ i ] = NULL;
464                 }
465
466                 /* -fs_homepath - sets both of them */
467                 else if( strcmp( argv[ i ], "-fs_homepath" ) == 0 )
468                 {
469                         if( ++i >= *argc )
470                                 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
471                         argv[ i - 1 ] = NULL;
472                         homePath = argv[i];
473                         homeBasePath = ".";
474                         argv[ i ] = NULL;
475                 }
476         }
477         
478         /* remove processed arguments */
479         for( i = 0, j = 0, k = 0; i < *argc && j < *argc; i++, j++ )
480         {
481                 for( ; j < *argc && argv[ j ] == NULL; j++ );
482                 argv[ i ] = argv[ j ];
483                 if( argv[ i ] != NULL )
484                         k++;
485         }
486         *argc = k;
487         
488         /* add standard game path */
489         AddGamePath( game->gamePath );
490         
491         /* if there is no base path set, figure it out */
492         if( numBasePaths == 0 )
493         {
494                 /* this is another crappy replacement for SetQdirFromPath() */
495                 len2 = strlen( game->magic );
496                 for( i = 0; i < *argc && numBasePaths == 0; i++ )
497                 {
498                         /* extract the arg */
499                         strcpy( temp, argv[ i ] );
500                         CleanPath( temp );
501                         len = strlen( temp );
502                         Sys_FPrintf( SYS_VRB, "Searching for \"%s\" in \"%s\" (%d)...\n", game->magic, temp, i );
503                         
504                         /* this is slow, but only done once */
505                         for( j = 0; j < (len - len2); j++ )
506                         {
507                                 /* check for the game's magic word */
508                                 if( Q_strncasecmp( &temp[ j ], game->magic, len2 ) == 0 )
509                                 {
510                                         /* now find the next slash and nuke everything after it */
511                                         while( temp[ ++j ] != '/' && temp[ j ] != '\0' );
512                                         temp[ j ] = '\0';
513                                         
514                                         /* add this as a base path */
515                                         AddBasePath( temp );
516                                         break;
517                                 }
518                         }
519                 }
520                 
521                 /* add install path */
522                 if( numBasePaths == 0 )
523                         AddBasePath( installPath );
524                 
525                 /* check again */
526                 if( numBasePaths == 0 )
527                         Error( "Failed to find a valid base path." );
528         }
529         
530         /* this only affects unix */
531         if(homeBasePath)
532                 AddHomeBasePath( homeBasePath );
533         else
534                 AddHomeBasePath( game->homeBasePath );
535         
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;
541         
542         /* walk the list of game paths */
543         for( j = 0; j < numGamePaths; j++ )
544         {
545                 /* walk the list of base paths */
546                 for( i = 0; i < numBasePaths; i++ )
547                 {
548                         /* create a full path and initialize it */
549                         sprintf( temp, "%s/%s/", basePaths[ i ], gamePaths[ j ] );
550                         vfsInitDirectory( temp );
551                 }
552         }
553         
554         /* done */
555         Sys_Printf( "\n" );
556 }
557
558
559
560