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