]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake3/q3map2/path_init.c
eol style
[xonotic/netradiant.git] / tools / quake3 / q3map2 / path_init.c
1 /*
2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20
21 ----------------------------------------------------------------------------------
22
23 This code has been altered significantly from its original form, to support
24 several games based on the Quake III Arena engine, in the form of "Q3Map2."
25
26 ------------------------------------------------------------------------------- */
27
28
29
30 /* marker */
31 #define PATH_INIT_C
32
33
34
35 /* dependencies */
36 #include "q3map2.h"
37
38
39
40 /* path support */
41 #define MAX_BASE_PATHS  10
42 #define MAX_GAME_PATHS  10
43
44 char                                    *homePath;
45 char                                    installPath[ MAX_OS_PATH ];
46
47 int                                             numBasePaths;
48 char                                    *basePaths[ MAX_BASE_PATHS ];
49 int                                             numGamePaths;
50 char                                    *gamePaths[ MAX_GAME_PATHS ];
51
52
53
54 /*
55 some of this code is based off the original q3map port from loki
56 and finds various paths. moved here from bsp.c for clarity.
57 */
58
59 /*
60 PathLokiGetHomeDir()
61 gets the user's home dir (for ~/.q3a)
62 */
63
64 char *LokiGetHomeDir( void )
65 {
66         #ifndef Q_UNIX
67                 return NULL;
68         #else
69                 char                    *home;
70                 uid_t                   id;
71                 struct passwd   *pwd;
72                 
73                 
74                 /* get the home environment variable */
75                 home = getenv( "HOME" );
76                 if( home == NULL )
77                 {
78                         /* do some more digging */
79                         id = getuid();
80                         setpwent();
81                         while( (pwd = getpwent()) != NULL )
82                         {
83                                 if( pwd->pw_uid == id )
84                                 {
85                                         home = pwd->pw_dir;
86                                         break;
87                                 }
88                         }
89                         endpwent();
90                 }
91                 
92                 /* return it */
93                 return home;
94         #endif
95 }
96
97
98
99 /*
100 PathLokiInitPaths()
101 initializes some paths on linux/os x
102 */
103
104 void LokiInitPaths( char *argv0 )
105 {
106         #ifndef Q_UNIX
107                 /* this is kinda crap, but hey */
108                 strcpy( installPath, "../" );
109         #else
110                 char            temp[ MAX_OS_PATH ];
111                 char            *home;
112                 char            *path;
113                 char            *last;
114                 qboolean        found;
115                 
116                 
117                 /* get home dir */
118                 home = LokiGetHomeDir();
119                 if( home == NULL )
120                         home = ".";
121                 
122                 /* do some path divining */
123                 strcpy( temp, argv0 );
124                 if( strrchr( temp, '/' ) )
125                         argv0 = strrchr( argv0, '/' ) + 1;
126                 else
127                 {
128                         /* get path environment variable */
129                         path = getenv( "PATH" );
130                         
131                         /* minor setup */
132                         last[ 0 ] = path[ 0 ];
133                         last[ 1 ] = '\0';
134                         found = qfalse;
135                         
136                         /* go through each : segment of path */
137                         while( last[ 0 ] != '\0' && found == qfalse )
138                         {
139                                 /* null out temp */
140                                 temp[ 0 ] = '\0';
141                                 
142                                 /* find next chunk */
143                                 last = strchr( path, ':' );
144                                 if( last == NULL )
145                                         last = path + strlen( path );
146                                 
147                                 /* found home dir candidate */
148                                 if( *path == '~' )
149                                 {
150                                         strcpy( temp, home );
151                                         path++;
152                                 }
153                                 
154                                 /* concatenate */
155                                 if( last > (path + 1) )
156                                 {
157                                         strncat( temp, path, (last - path) );
158                                         strcat( temp, "/" );
159                                 }
160                                 strcat( temp, "./" );
161                                 strcat( temp, argv0 );
162                                 
163                                 /* verify the path */
164                                 if( access( temp, X_OK ) == 0 )
165                                         found++;
166                                 path = last + 1;
167                         }
168                 }
169                 
170                 /* flake */
171                 if( realpath( temp, installPath ) )
172                 {
173                         /* q3map is in "tools/" */
174                         *(strrchr( installPath, '/' )) = '\0';
175                         *(strrchr( installPath, '/' ) + 1) = '\0';
176                 }
177                 
178                 /* set home path */
179                 homePath = home;
180         #endif
181 }
182
183
184
185 /*
186 CleanPath() - ydnar
187 cleans a dos path \ -> /
188 */
189
190 void CleanPath( char *path )
191 {
192         while( *path )
193         {
194                 if( *path == '\\' )
195                         *path = '/';
196                 path++;
197         }
198 }
199
200
201
202 /*
203 SetGame() - ydnar
204 sets the game based on a -game argument
205 doesn't set it if the game doesn't match any known games
206 */
207
208 void SetGame( char *arg )
209 {
210         int     i;
211         
212         
213         /* dummy check */
214         if( arg == NULL || arg[ 0 ] == '\0' )
215                 return;
216         
217         /* joke */
218         if( !Q_stricmp( arg, "quake1" ) ||
219                 !Q_stricmp( arg, "quake2" ) ||
220                 !Q_stricmp( arg, "unreal" ) ||
221                 !Q_stricmp( arg, "ut2k3" ) ||
222                 !Q_stricmp( arg, "dn3d" ) ||
223                 !Q_stricmp( arg, "dnf" ) ||
224                 !Q_stricmp( arg, "hl" ) )
225         {
226                 Sys_Printf( "April fools, silly rabbit!\n" );
227                 exit( 0 );
228         }
229         
230         /* test it */
231         i = 0;
232         while( games[ i ].arg != NULL )
233         {
234                 if( Q_stricmp( arg, games[ i ].arg ) == 0 )
235                         game = &games[ i ];
236                 i++;
237         }
238 }
239
240
241
242 /*
243 AddBasePath() - ydnar
244 adds a base path to the list
245 */
246
247 void AddBasePath( char *path )
248 {
249         /* dummy check */
250         if( path == NULL || path[ 0 ] == '\0' || numBasePaths >= MAX_BASE_PATHS )
251                 return;
252         
253         /* add it to the list */
254         basePaths[ numBasePaths ] = safe_malloc( strlen( path ) + 1 );
255         strcpy( basePaths[ numBasePaths ], path );
256         CleanPath( basePaths[ numBasePaths ] );
257         numBasePaths++;
258 }
259
260
261
262 /*
263 AddHomeBasePath() - ydnar
264 adds a base path to the beginning of the list, prefixed by ~/
265 */
266
267 void AddHomeBasePath( char *path )
268 {
269         #ifdef Q_UNIX
270                 int             i;
271                 char    temp[ MAX_OS_PATH ];
272                 
273                 
274                 /* dummy check */
275                 if( path == NULL || path[ 0 ] == '\0' )
276                         return;
277
278                 /* make a hole */
279                 for( i = 0; i < (MAX_BASE_PATHS - 1); i++ )
280                         basePaths[ i + 1 ] = basePaths[ i ];
281                 
282                 /* concatenate home dir and path */
283                 sprintf( temp, "%s/%s", homePath, path );
284                 
285                 /* add it to the list */
286                 basePaths[ 0 ] = safe_malloc( strlen( temp ) + 1 );
287                 strcpy( basePaths[ 0 ], temp );
288                 CleanPath( basePaths[ 0 ] );
289                 numBasePaths++;
290         #endif
291 }
292
293
294
295 /*
296 AddGamePath() - ydnar
297 adds a game path to the list
298 */
299
300 void AddGamePath( char *path )
301 {
302         /* dummy check */
303         if( path == NULL || path[ 0 ] == '\0' || numGamePaths >= MAX_GAME_PATHS )
304                 return;
305         
306         /* add it to the list */
307         gamePaths[ numGamePaths ] = safe_malloc( strlen( path ) + 1 );
308         strcpy( gamePaths[ numGamePaths ], path );
309         CleanPath( gamePaths[ numGamePaths ] );
310         numGamePaths++;
311 }
312
313
314
315
316 /*
317 InitPaths() - ydnar
318 cleaned up some of the path initialization code from bsp.c
319 will remove any arguments it uses
320 */
321
322 void InitPaths( int *argc, char **argv )
323 {
324         int             i, j, k, len, len2;
325         char    temp[ MAX_OS_PATH ];
326         
327         
328         /* note it */
329         Sys_FPrintf( SYS_VRB, "--- InitPaths ---\n" );
330         
331         /* get the install path for backup */
332         LokiInitPaths( argv[ 0 ] );
333         
334         /* set game to default (q3a) */
335         game = &games[ 0 ];
336         numBasePaths = 0;
337         numGamePaths = 0;
338         
339         /* parse through the arguments and extract those relevant to paths */
340         for( i = 0; i < *argc; i++ )
341         {
342                 /* check for null */
343                 if( argv[ i ] == NULL )
344                         continue;
345                 
346                 /* -game */
347                 if( strcmp( argv[ i ], "-game" ) == 0 )
348                 {
349                         if( ++i >= *argc )
350                                 Error( "Out of arguments: No game specified after %s", argv[ i - 1 ] );
351                         argv[ i - 1 ] = NULL;
352                         SetGame( argv[ i ] );
353                         argv[ i ] = NULL;
354                 }
355
356                 /* -fs_basepath */
357                 else if( strcmp( argv[ i ], "-fs_basepath" ) == 0 )
358                 {
359                         if( ++i >= *argc )
360                                 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
361                         argv[ i - 1 ] = NULL;
362                         AddBasePath( argv[ i ] );
363                         argv[ i ] = NULL;
364                 }
365                 
366                 /* -fs_game */
367                 else if( strcmp( argv[ i ], "-fs_game" ) == 0 )
368                 {
369                         if( ++i >= *argc )
370                                 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
371                         argv[ i - 1 ] = NULL;
372                         AddGamePath( argv[ i ] );
373                         argv[ i ] = NULL;
374                 }
375         }
376         
377         /* remove processed arguments */
378         for( i = 0, j = 0, k = 0; i < *argc && j < *argc; i++, j++ )
379         {
380                 for( j; j < *argc && argv[ j ] == NULL; j++ );
381                 argv[ i ] = argv[ j ];
382                 if( argv[ i ] != NULL )
383                         k++;
384         }
385         *argc = k;
386         
387         /* add standard game path */
388         AddGamePath( game->gamePath );
389         
390         /* if there is no base path set, figure it out */
391         if( numBasePaths == 0 )
392         {
393                 /* this is another crappy replacement for SetQdirFromPath() */
394                 len2 = strlen( game->magic );
395                 for( i = 0; i < *argc && numBasePaths == 0; i++ )
396                 {
397                         /* extract the arg */
398                         strcpy( temp, argv[ i ] );
399                         CleanPath( temp );
400                         len = strlen( temp );
401                         Sys_FPrintf( SYS_VRB, "Searching for \"%s\" in \"%s\" (%d)...\n", game->magic, temp, i );
402                         
403                         /* this is slow, but only done once */
404                         for( j = 0; j < (len - len2); j++ )
405                         {
406                                 /* check for the game's magic word */
407                                 if( Q_strncasecmp( &temp[ j ], game->magic, len2 ) == 0 )
408                                 {
409                                         /* now find the next slash and nuke everything after it */
410                                         while( temp[ ++j ] != '/' && temp[ j ] != '\0' );
411                                         temp[ j ] = '\0';
412                                         
413                                         /* add this as a base path */
414                                         AddBasePath( temp );
415                                         break;
416                                 }
417                         }
418                 }
419                 
420                 /* add install path */
421                 if( numBasePaths == 0 )
422                         AddBasePath( installPath );
423                 
424                 /* check again */
425                 if( numBasePaths == 0 )
426                         Error( "Failed to find a valid base path." );
427         }
428         
429         /* this only affects unix */
430         AddHomeBasePath( game->homeBasePath );
431         
432         /* initialize vfs paths */
433         if( numBasePaths > MAX_BASE_PATHS )
434                 numBasePaths = MAX_BASE_PATHS;
435         if( numGamePaths > MAX_GAME_PATHS )
436                 numGamePaths = MAX_GAME_PATHS;
437         
438         /* walk the list of game paths */
439         for( j = 0; j < numGamePaths; j++ )
440         {
441                 /* walk the list of base paths */
442                 for( i = 0; i < numBasePaths; i++ )
443                 {
444                         /* create a full path and initialize it */
445                         sprintf( temp, "%s/%s/", basePaths[ i ], gamePaths[ j ] );
446                         vfsInitDirectory( temp );
447                 }
448         }
449         
450         /* done */
451         Sys_Printf( "\n" );
452 }
453
454
455
456