1 |
/*------------------------------------------------------------------. |
2 |
| Copyright 2001 Alexandre Duret-Lutz <duret_g@epita.fr> | |
3 |
| | |
4 |
| This file is part of Heroes. | |
5 |
| | |
6 |
| Heroes is free software; you can redistribute it and/or modify it | |
7 |
| under the terms of the GNU General Public License version 2 as | |
8 |
| published by the Free Software Foundation. | |
9 |
| | |
10 |
| Heroes is distributed in the hope that it will be useful, but | |
11 |
| WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 |
| General Public License for more details. | |
14 |
| | |
15 |
| You should have received a copy of the GNU General Public License | |
16 |
| along with this program; if not, write to the Free Software | |
17 |
| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | |
18 |
| 02111-1307 USA | |
19 |
`------------------------------------------------------------------*/ |
20 |
|
21 |
#include "system.h" |
22 |
#include "relocate.h" |
23 |
#include "debugmsg.h" |
24 |
#include "errors.h" |
25 |
#include "isdir.h" |
26 |
#include "rsc_files.h" |
27 |
#include "dirname.h" |
28 |
#include "misc.h" |
29 |
|
30 |
static void |
31 |
check_localedir_env (void) |
32 |
{ |
33 |
char* locale_dir; |
34 |
dmsg (D_SYSTEM, "looking for HEROES_LOCALE_DIR or HEROES_LOCALEDIR..."); |
35 |
if ((locale_dir = getenv ("HEROES_LOCALE_DIR")) || |
36 |
(locale_dir = getenv ("HEROES_LOCALEDIR"))) { |
37 |
dmsg (D_SYSTEM,"... found: %s", locale_dir); |
38 |
set_rsc_file ("locale-dir", locale_dir, false); |
39 |
} else { |
40 |
dmsg (D_SYSTEM, "... not found."); |
41 |
} |
42 |
} |
43 |
|
44 |
static void |
45 |
check_datadir_env (void) |
46 |
{ |
47 |
char* data_dir; |
48 |
dmsg (D_SYSTEM, "looking for HEROES_DATA_DIR or HEROES_DATADIR..."); |
49 |
if ((data_dir = getenv ("HEROES_DATA_DIR")) || |
50 |
(data_dir = getenv ("HEROES_DATADIR"))) { |
51 |
dmsg (D_SYSTEM,"... found: %s", data_dir); |
52 |
set_rsc_file ("data-dir", data_dir, false); |
53 |
} else { |
54 |
dmsg (D_SYSTEM, "... not found."); |
55 |
} |
56 |
} |
57 |
|
58 |
static void |
59 |
check_plugindir_env (void) |
60 |
{ |
61 |
char* data_dir; |
62 |
dmsg (D_SYSTEM, "looking for HEROES_PLUG_IN_DIR or HEROES_PLUGIN_DIR or" |
63 |
" HEROES_PLUGINDIR ..."); |
64 |
if ((data_dir = getenv ("HEROES_PLUG_IN_DIR")) || |
65 |
(data_dir = getenv ("HEROES_PLUGIN_DIR")) || |
66 |
(data_dir = getenv ("HEROES_PLUGINDIR"))) { |
67 |
dmsg (D_SYSTEM,"... found: %s", data_dir); |
68 |
set_rsc_file ("plug-in-dir", data_dir, false); |
69 |
} else { |
70 |
dmsg (D_SYSTEM, "... not found."); |
71 |
} |
72 |
} |
73 |
|
74 |
static void |
75 |
check_homedir_env (void) |
76 |
{ |
77 |
char* home_dir; |
78 |
dmsg (D_SYSTEM, "looking for HEROES_HOME_DIR, HEROES_HOMEDIR or HOME..."); |
79 |
if ((home_dir = getenv ("HEROES_HOME_DIR")) || |
80 |
(home_dir = getenv ("HEROES_HOMEDIR")) || |
81 |
(home_dir = getenv ("HOME"))) { |
82 |
dmsg (D_SYSTEM,"... found: %s", home_dir); |
83 |
set_rsc_file ("home-dir", home_dir, false); |
84 |
} else { |
85 |
dmsg (D_SYSTEM, "... not found."); |
86 |
wmsg (_("HOME variable not found in environment, defaulting to `.'")); |
87 |
set_rsc_file ("home-dir", ".", false); |
88 |
} |
89 |
} |
90 |
|
91 |
static bool |
92 |
check_prefix_env (void) |
93 |
{ |
94 |
char* prefix; |
95 |
dmsg (D_SYSTEM, "looking for HEROES_PREFIX ..."); |
96 |
if ((prefix = getenv ("HEROES_PREFIX"))) { |
97 |
dmsg (D_SYSTEM,"... found: %s", prefix); |
98 |
set_rsc_file ("prefix", prefix, false); |
99 |
return true; |
100 |
} else { |
101 |
dmsg (D_SYSTEM, "... not found."); |
102 |
return false; |
103 |
} |
104 |
} |
105 |
|
106 |
/* Check whether the installation looks correct. */ |
107 |
static bool |
108 |
check_installation (void) |
109 |
{ |
110 |
char *dir = get_non_null_rsc_file ("levels-dir"); |
111 |
bool ok; |
112 |
|
113 |
strip_trailing_slashes (dir); |
114 |
ok = isdir (dir); |
115 |
dmsg (D_SYSTEM, |
116 |
ok ? "directory %s found": "%s absent or not a directory", |
117 |
dir); |
118 |
free (dir); |
119 |
return ok; |
120 |
} |
121 |
|
122 |
/* Compute prefix from argv0, if possible. */ |
123 |
static bool |
124 |
try_to_derive_argv0 (const char *argv0) |
125 |
{ |
126 |
/* Compute PREFIX using argv0. */ |
127 |
char *path = dir_name (argv0); |
128 |
if (path) { |
129 |
path = strappend (path, "/" BACKWARD_RELATIVE_BINDIR); |
130 |
set_rsc_file ("prefix", path, false); |
131 |
dmsg (D_SYSTEM, "trying $(prefix)='%s'", path); |
132 |
} |
133 |
XFREE (path); |
134 |
return check_installation (); |
135 |
} |
136 |
|
137 |
static bool |
138 |
try_backward_relative_bindir (void) |
139 |
{ |
140 |
/* BACKWARD_RELATIVE_BINDIR is in case the binary has been |
141 |
run from the current directory. */ |
142 |
dmsg (D_SYSTEM, "trying $(prefix)='%s'", BACKWARD_RELATIVE_BINDIR); |
143 |
set_rsc_file ("prefix", BACKWARD_RELATIVE_BINDIR, false); |
144 |
return check_installation (); |
145 |
} |
146 |
|
147 |
static bool |
148 |
try_to_explore_path (void) |
149 |
{ |
150 |
char *path_env = getenv ("PATH"); |
151 |
char *path; |
152 |
char *last; |
153 |
bool curdir_is_ok = false; |
154 |
const char *pathsep; |
155 |
|
156 |
if (!path_env) |
157 |
return false; |
158 |
|
159 |
/* If a semicolon is present in the PATH, assume it is the PATH |
160 |
separator character, otherwise we'll use a colon. */ |
161 |
pathsep = strchr (path_env, ';') ? ";" : ":"; |
162 |
|
163 |
/* Duplicate the string because it will be destroyed by strtok. */ |
164 |
path = xstrdup (path_env); |
165 |
|
166 |
last = strtok (path, pathsep); |
167 |
while (last) { |
168 |
char *dir = strcat_alloc (last, "/" BACKWARD_RELATIVE_BINDIR); |
169 |
dmsg (D_SYSTEM, "trying $(prefix)='%s'", dir); |
170 |
set_rsc_file ("prefix", dir, false); |
171 |
free (dir); |
172 |
if (check_installation ()) { |
173 |
curdir_is_ok = true; |
174 |
break; |
175 |
} |
176 |
last = strtok (0, pathsep); |
177 |
} |
178 |
free (path); |
179 |
return curdir_is_ok; |
180 |
} |
181 |
|
182 |
bool |
183 |
relocate_data (const char *argv0) |
184 |
{ |
185 |
/* Check whether the user has set some environment variables to |
186 |
override internal paths. */ |
187 |
check_datadir_env (); |
188 |
check_plugindir_env (); |
189 |
check_localedir_env (); |
190 |
check_homedir_env (); |
191 |
if (!check_prefix_env ()) { |
192 |
if (!check_installation ()) { |
193 |
/* IF the user has not set HEROES_PREFIX and Heroes can't find |
194 |
its files, try to guess the prefix. */ |
195 |
dmsg (D_SYSTEM, "default prefix looks wrong"); |
196 |
if (!try_to_derive_argv0 (argv0)) { |
197 |
if (!try_to_explore_path ()) { |
198 |
if (!try_backward_relative_bindir ()) |
199 |
emsg (_("\ |
200 |
It looks like the game is not correctly installed.\n\ |
201 |
Maybe the data files have not been installed with the same configure options\n\ |
202 |
as the executable, or maybe the data files have been moved elsewhere.\n\ |
203 |
In the latter case it's probably enough to set the environment variable\n\ |
204 |
HEROES_PREFIX to the new location. You may also want to set\n\ |
205 |
HEROES_DEBUG=system to see what files Heroes is looking after.\n\ |
206 |
If none of this helps, contact <heroes-bugs@lists.sourceforge.net>\n")); |
207 |
} |
208 |
} |
209 |
} |
210 |
} |
211 |
return false; |
212 |
} |