]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake3/q3map2/path_init.c
Merge remote-tracking branch 'origin/divVerent/weird-shift-a'
[xonotic/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                 
74                 
75                 /* get the home environment variable */
76                 home = getenv( "HOME" );
77                 if( home == NULL )
78                 {
79                         /* do some more digging */
80                         id = getuid();
81                         setpwent();
82                         while( (pwd = getpwent()) != NULL )
83                         {
84                                 if( pwd->pw_uid == id )
85                                 {
86                                         home = pwd->pw_dir;
87                                         break;
88                                 }
89                         }
90                         endpwent();
91                 }
92                 
93                 /* return it */
94                 return home;
95         #endif
96 }
97
98
99
100 /*
101 PathLokiInitPaths()
102 initializes some paths on linux/os x
103 */
104
105 void LokiInitPaths( char *argv0 )
106 {
107         #ifndef Q_UNIX
108                 /* this is kinda crap, but hey */
109                 strcpy( installPath, "../" );
110         #else
111                 char            temp[ MAX_OS_PATH ];
112                 char            last0[ 2 ];
113                 char            *home;
114                 char            *path;
115                 char            *last;
116                 qboolean        found;
117                 
118                 
119                 /* get home dir */
120                 home = LokiGetHomeDir();
121                 if( home == NULL )
122                         home = ".";
123                 
124                 /* do some path divining */
125                 strcpy( temp, argv0 );
126                 if( strrchr( argv0, '/' ) )
127                         argv0 = strrchr( argv0, '/' ) + 1;
128                 else
129                 {
130                         /* get path environment variable */
131                         path = getenv( "PATH" );
132                         
133                         /* minor setup */
134                         last = last0;
135                         last[ 0 ] = path[ 0 ];
136                         last[ 1 ] = '\0';
137                         found = qfalse;
138                         
139                         /* go through each : segment of path */
140                         while( last[ 0 ] != '\0' && found == qfalse )
141                         {
142                                 /* null out temp */
143                                 temp[ 0 ] = '\0';
144                                 
145                                 /* find next chunk */
146                                 last = strchr( path, ':' );
147                                 if( last == NULL )
148                                         last = path + strlen( path );
149                                 
150                                 /* found home dir candidate */
151                                 if( *path == '~' )
152                                 {
153                                         strcpy( temp, home );
154                                         path++;
155                                 }
156                                 
157                                 /* concatenate */
158                                 if( last > (path + 1) )
159                                 {
160                                         strncat( temp, path, (last - path) );
161                                         strcat( temp, "/" );
162                                 }
163                                 strcat( temp, "./" );
164                                 strcat( temp, argv0 );
165                                 
166                                 /* verify the path */
167                                 if( access( temp, X_OK ) == 0 )
168                                         found++;
169                                 path = last + 1;
170                         }
171                 }
172                 
173                 /* flake */
174                 if( realpath( temp, installPath ) )
175                 {
176                         /* q3map is in "tools/" */
177                         *(strrchr( installPath, '/' )) = '\0';
178                         *(strrchr( installPath, '/' ) + 1) = '\0';
179                 }
180                 
181                 /* set home path */
182                 homePath = home;
183         #endif
184 }
185
186
187
188 /*
189 CleanPath() - ydnar
190 cleans a dos path \ -> /
191 */
192
193 void CleanPath( char *path )
194 {
195         while( *path )
196         {
197                 if( *path == '\\' )
198                         *path = '/';
199                 path++;
200         }
201 }
202
203
204
205 /*
206 GetGame() - ydnar
207 gets the game_t based on a -game argument
208 returns NULL if no match found
209 */
210
211 game_t *GetGame( char *arg )
212 {
213         int     i;
214         
215         
216         /* dummy check */
217         if( arg == NULL || arg[ 0 ] == '\0' )
218                 return NULL;
219         
220         /* joke */
221         if( !Q_stricmp( arg, "quake1" ) ||
222                 !Q_stricmp( arg, "quake2" ) ||
223                 !Q_stricmp( arg, "unreal" ) ||
224                 !Q_stricmp( arg, "ut2k3" ) ||
225                 !Q_stricmp( arg, "dn3d" ) ||
226                 !Q_stricmp( arg, "dnf" ) ||
227                 !Q_stricmp( arg, "hl" ) )
228         {
229                 Sys_Printf( "April fools, silly rabbit!\n" );
230                 exit( 0 );
231         }
232         
233         /* test it */
234         i = 0;
235         while( games[ i ].arg != NULL )
236         {
237                 if( Q_stricmp( arg, games[ i ].arg ) == 0 )
238                         return &games[ i ];
239                 i++;
240         }
241         
242         /* no matching game */
243         return NULL;
244 }
245
246
247
248 /*
249 AddBasePath() - ydnar
250 adds a base path to the list
251 */
252
253 void AddBasePath( char *path )
254 {
255         /* dummy check */
256         if( path == NULL || path[ 0 ] == '\0' || numBasePaths >= MAX_BASE_PATHS )
257                 return;
258         
259         /* add it to the list */
260         basePaths[ numBasePaths ] = safe_malloc( strlen( path ) + 1 );
261         strcpy( basePaths[ numBasePaths ], path );
262         CleanPath( basePaths[ numBasePaths ] );
263         numBasePaths++;
264 }
265
266
267
268 /*
269 AddHomeBasePath() - ydnar
270 adds a base path to the beginning of the list, prefixed by ~/
271 */
272
273 void AddHomeBasePath( char *path )
274 {
275         #ifdef Q_UNIX
276                 int             i;
277                 char    temp[ MAX_OS_PATH ];
278                 
279                 
280                 /* dummy check */
281                 if( path == NULL || path[ 0 ] == '\0' )
282                         return;
283
284                 /* make a hole */
285                 for( i = (MAX_BASE_PATHS - 2); i >= 0; i-- )
286                         basePaths[ i + 1 ] = basePaths[ i ];
287                 
288                 /* concatenate home dir and path */
289                 sprintf( temp, "%s/%s", homePath, path );
290                 
291                 /* add it to the list */
292                 basePaths[ 0 ] = safe_malloc( strlen( temp ) + 1 );
293                 strcpy( basePaths[ 0 ], temp );
294                 CleanPath( basePaths[ 0 ] );
295                 numBasePaths++;
296         #endif
297 }
298
299
300
301 /*
302 AddGamePath() - ydnar
303 adds a game path to the list
304 */
305
306 void AddGamePath( char *path )
307 {
308         int     i;
309
310         /* dummy check */
311         if( path == NULL || path[ 0 ] == '\0' || numGamePaths >= MAX_GAME_PATHS )
312                 return;
313         
314         /* add it to the list */
315         gamePaths[ numGamePaths ] = safe_malloc( strlen( path ) + 1 );
316         strcpy( gamePaths[ numGamePaths ], path );
317         CleanPath( gamePaths[ numGamePaths ] );
318         numGamePaths++;
319
320         /* don't add it if it's already there */
321         for (i = 0; i < numGamePaths - 1; i++)
322         {
323                 if (strcmp(gamePaths[i], gamePaths[numGamePaths - 1]) == 0)
324                 {
325                         free(gamePaths[numGamePaths - 1]);
326                         gamePaths[numGamePaths - 1] = NULL;
327                         numGamePaths--;
328                         break;
329                 }
330         }
331         
332 }
333
334
335
336
337 /*
338 InitPaths() - ydnar
339 cleaned up some of the path initialization code from bsp.c
340 will remove any arguments it uses
341 */
342
343 void InitPaths( int *argc, char **argv )
344 {
345         int             i, j, k, len, len2;
346         char    temp[ MAX_OS_PATH ];
347         
348         
349         /* note it */
350         Sys_FPrintf( SYS_VRB, "--- InitPaths ---\n" );
351         
352         /* get the install path for backup */
353         LokiInitPaths( argv[ 0 ] );
354         
355         /* set game to default (q3a) */
356         game = &games[ 0 ];
357         numBasePaths = 0;
358         numGamePaths = 0;
359         
360         /* parse through the arguments and extract those relevant to paths */
361         for( i = 0; i < *argc; i++ )
362         {
363                 /* check for null */
364                 if( argv[ i ] == NULL )
365                         continue;
366                 
367                 /* -game */
368                 if( strcmp( argv[ i ], "-game" ) == 0 )
369                 {
370                         if( ++i >= *argc )
371                                 Error( "Out of arguments: No game specified after %s", argv[ i - 1 ] );
372                         argv[ i - 1 ] = NULL;
373                         game = GetGame( argv[ i ] );
374                         if( game == NULL )
375                                 game = &games[ 0 ];
376                         argv[ i ] = NULL;
377                 }
378
379                 /* -fs_forbiddenpath */
380                 else if( strcmp( argv[ i ], "-fs_forbiddenpath" ) == 0 )
381                 {
382                         if( ++i >= *argc )
383                                 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
384                         argv[ i - 1 ] = NULL;
385                         if(g_numForbiddenDirs < VFS_MAXDIRS)
386                         {
387                                 strncpy(g_strForbiddenDirs[g_numForbiddenDirs], argv[i], PATH_MAX);
388                                 g_strForbiddenDirs[g_numForbiddenDirs][PATH_MAX] = 0;
389                                 ++g_numForbiddenDirs;
390                         }
391                         argv[ i ] = NULL;
392                 }
393
394                 /* -fs_basepath */
395                 else if( strcmp( argv[ i ], "-fs_basepath" ) == 0 )
396                 {
397                         if( ++i >= *argc )
398                                 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
399                         argv[ i - 1 ] = NULL;
400                         AddBasePath( argv[ i ] );
401                         argv[ i ] = NULL;
402                 }
403                 
404                 /* -fs_game */
405                 else if( strcmp( argv[ i ], "-fs_game" ) == 0 )
406                 {
407                         if( ++i >= *argc )
408                                 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
409                         argv[ i - 1 ] = NULL;
410                         AddGamePath( argv[ i ] );
411                         argv[ i ] = NULL;
412                 }
413                 
414                 /* -fs_nohomebase */
415                 else if( strcmp( argv[ i ], "-fs_homebase" ) == 0 )
416                 {
417                         if( ++i >= *argc )
418                                 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
419                         argv[ i - 1 ] = NULL;
420                         homeBasePath = argv[i];
421                         argv[ i ] = NULL;
422                 }
423         }
424         
425         /* remove processed arguments */
426         for( i = 0, j = 0, k = 0; i < *argc && j < *argc; i++, j++ )
427         {
428                 for( ; j < *argc && argv[ j ] == NULL; j++ );
429                 argv[ i ] = argv[ j ];
430                 if( argv[ i ] != NULL )
431                         k++;
432         }
433         *argc = k;
434         
435         /* add standard game path */
436         AddGamePath( game->gamePath );
437         
438         /* if there is no base path set, figure it out */
439         if( numBasePaths == 0 )
440         {
441                 /* this is another crappy replacement for SetQdirFromPath() */
442                 len2 = strlen( game->magic );
443                 for( i = 0; i < *argc && numBasePaths == 0; i++ )
444                 {
445                         /* extract the arg */
446                         strcpy( temp, argv[ i ] );
447                         CleanPath( temp );
448                         len = strlen( temp );
449                         Sys_FPrintf( SYS_VRB, "Searching for \"%s\" in \"%s\" (%d)...\n", game->magic, temp, i );
450                         
451                         /* this is slow, but only done once */
452                         for( j = 0; j < (len - len2); j++ )
453                         {
454                                 /* check for the game's magic word */
455                                 if( Q_strncasecmp( &temp[ j ], game->magic, len2 ) == 0 )
456                                 {
457                                         /* now find the next slash and nuke everything after it */
458                                         while( temp[ ++j ] != '/' && temp[ j ] != '\0' );
459                                         temp[ j ] = '\0';
460                                         
461                                         /* add this as a base path */
462                                         AddBasePath( temp );
463                                         break;
464                                 }
465                         }
466                 }
467                 
468                 /* add install path */
469                 if( numBasePaths == 0 )
470                         AddBasePath( installPath );
471                 
472                 /* check again */
473                 if( numBasePaths == 0 )
474                         Error( "Failed to find a valid base path." );
475         }
476         
477         /* this only affects unix */
478         if(homeBasePath)
479                 AddHomeBasePath( homeBasePath );
480         else
481                 AddHomeBasePath( game->homeBasePath );
482         
483         /* initialize vfs paths */
484         if( numBasePaths > MAX_BASE_PATHS )
485                 numBasePaths = MAX_BASE_PATHS;
486         if( numGamePaths > MAX_GAME_PATHS )
487                 numGamePaths = MAX_GAME_PATHS;
488         
489         /* walk the list of game paths */
490         for( j = 0; j < numGamePaths; j++ )
491         {
492                 /* walk the list of base paths */
493                 for( i = 0; i < numBasePaths; i++ )
494                 {
495                         /* create a full path and initialize it */
496                         sprintf( temp, "%s/%s/", basePaths[ i ], gamePaths[ j ] );
497                         vfsInitDirectory( temp );
498                 }
499         }
500         
501         /* done */
502         Sys_Printf( "\n" );
503 }
504
505
506
507