f92b291acd5059ca35c6fc257746afb5e7760a0b
[oweals/minetest.git] / src / porting.cpp
1 /*
2 Minetest-c55
3 Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 /*
21         Random portability stuff
22
23         See comments in porting.h
24 */
25
26 #include "porting.h"
27 #include "config.h"
28
29 namespace porting
30 {
31
32 /*
33         Signal handler (grabs Ctrl-C on POSIX systems)
34 */
35
36 #if !defined(_WIN32) // POSIX
37         #include <signal.h>
38
39 bool g_killed = false;
40
41 void sigint_handler(int sig)
42 {
43         if(g_killed == false)
44         {
45                 dstream<<DTIME<<"sigint_handler(): "
46                                 <<"Ctrl-C pressed, shutting down."<<std::endl;
47                 g_killed = true;
48         }
49         else
50         {
51                 (void)signal(SIGINT, SIG_DFL);
52         }
53 }
54
55 void signal_handler_init(void)
56 {
57         dstream<<"signal_handler_init()"<<std::endl;
58         (void)signal(SIGINT, sigint_handler);
59 }
60
61 #else // _WIN32
62
63 void signal_handler_init(void)
64 {
65         // No-op
66 }
67
68 #endif
69
70 bool * signal_handler_killstatus(void)
71 {
72         return &g_killed;
73 }
74
75 /*
76         Path mangler
77 */
78
79 std::string path_data = "../data";
80 std::string path_userdata = "../";
81
82 void pathRemoveFile(char *path, char delim)
83 {
84         // Remove filename and path delimiter
85         int i;
86         for(i = strlen(path)-1; i>=0; i--)
87         {
88                 if(path[i] == delim)
89                         break;
90         }
91         path[i] = 0;
92 }
93
94 void initializePaths()
95 {
96 #ifdef RUN_IN_PLACE
97         /*
98                 Use relative paths if RUN_IN_PLACE
99         */
100
101         dstream<<"Using relative paths (RUN_IN_PLACE)"<<std::endl;
102
103         /*
104                 Windows
105         */
106         #if defined(_WIN32)
107                 #include <windows.h>
108
109         const DWORD buflen = 1000;
110         char buf[buflen];
111         DWORD len;
112         
113         // Find path of executable and set path_data relative to it
114         len = GetModuleFileName(GetModuleHandle(NULL), buf, buflen);
115         assert(len < buflen);
116         pathRemoveFile(buf, '\\');
117
118         // Use "./bin/../data"
119         path_data = std::string(buf) + "/../data";
120                 
121         // Use "./bin/../"
122         path_userdata = std::string(buf) + "/../";
123
124         /*
125                 Linux
126         */
127         #elif defined(linux)
128                 #include <unistd.h>
129         
130         char buf[BUFSIZ];
131         memset(buf, 0, BUFSIZ);
132         // Get path to executable
133         readlink("/proc/self/exe", buf, BUFSIZ-1);
134         
135         pathRemoveFile(buf, '/');
136
137         // Use "./bin/../data"
138         path_data = std::string(buf) + "/../data";
139                 
140         // Use "./bin/../"
141         path_userdata = std::string(buf) + "/../";
142         
143         /*
144                 OS X
145         */
146         #elif defined(__APPLE__)
147         
148         //TODO: Get path of executable. This assumes working directory is bin/
149         dstream<<"WARNING: Relative path not properly supported on OS X"
150                         <<std::endl;
151         path_data = std::string("../data");
152         path_userdata = std::string("../");
153
154         #endif
155
156 #else // RUN_IN_PLACE
157
158         /*
159                 Use platform-specific paths otherwise
160         */
161
162         dstream<<"Using system-wide paths (NOT RUN_IN_PLACE)"<<std::endl;
163
164         /*
165                 Windows
166         */
167         #if defined(_WIN32)
168                 #include <windows.h>
169
170         const DWORD buflen = 1000;
171         char buf[buflen];
172         DWORD len;
173         
174         // Find path of executable and set path_data relative to it
175         len = GetModuleFileName(GetModuleHandle(NULL), buf, buflen);
176         assert(len < buflen);
177         pathRemoveFile(buf, '\\');
178         
179         // Use "./bin/../data"
180         path_data = std::string(buf) + "/../data";
181         //path_data = std::string(buf) + "/../share/" + APPNAME;
182                 
183         // Use "C:\Documents and Settings\user\Application Data\<APPNAME>"
184         len = GetEnvironmentVariable("APPDATA", buf, buflen);
185         assert(len < buflen);
186         path_userdata = std::string(buf) + "/" + APPNAME;
187
188         /*
189                 Linux
190         */
191         #elif defined(linux)
192                 #include <unistd.h>
193         
194         char buf[BUFSIZ];
195         memset(buf, 0, BUFSIZ);
196         // Get path to executable
197         readlink("/proc/self/exe", buf, BUFSIZ-1);
198         
199         pathRemoveFile(buf, '/');
200
201         path_data = std::string(buf) + "/../share/" + APPNAME;
202         //path_data = std::string(INSTALL_PREFIX) + "/share/" + APPNAME;
203         
204         path_userdata = std::string(getenv("HOME")) + "/." + APPNAME;
205
206         /*
207                 OS X
208         */
209         #elif defined(__APPLE__)
210                 #include <unistd.h>
211
212         path_userdata = std::string(getenv("HOME")) + "/Library/Application Support/" + APPNAME;
213         path_data = std::string("minetest-mac.app/Contents/Resources/data/");
214
215         #endif
216
217 #endif // RUN_IN_PLACE
218
219         dstream<<"path_data = "<<path_data<<std::endl;
220         dstream<<"path_userdata = "<<path_userdata<<std::endl;
221 }
222
223 } //namespace porting
224