OpenTTD Source  1.10.1
unix.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of OpenTTD.
3  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6  */
7 
10 #include "../../stdafx.h"
11 #include "../../textbuf_gui.h"
12 #include "../../openttd.h"
13 #include "../../crashlog.h"
14 #include "../../core/random_func.hpp"
15 #include "../../debug.h"
16 #include "../../string_func.h"
17 #include "../../fios.h"
18 #include "../../thread.h"
19 
20 
21 #include <dirent.h>
22 #include <unistd.h>
23 #include <sys/stat.h>
24 #include <time.h>
25 #include <signal.h>
26 
27 #ifdef WITH_SDL2
28 #include <SDL.h>
29 #endif
30 
31 #ifdef __APPLE__
32  #include <sys/mount.h>
33 #elif (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L) || defined(__GLIBC__)
34  #define HAS_STATVFS
35 #endif
36 
37 #if defined(OPENBSD) || defined(__NetBSD__) || defined(__FreeBSD__)
38  #define HAS_SYSCTL
39 #endif
40 
41 #ifdef HAS_STATVFS
42 #include <sys/statvfs.h>
43 #endif
44 
45 #ifdef HAS_SYSCTL
46 #include <sys/sysctl.h>
47 #endif
48 
49 #ifndef NO_THREADS
50 #include <pthread.h>
51 #endif
52 
53 #if defined(__APPLE__)
54 # if defined(WITH_SDL)
55  /* the mac implementation needs this file included in the same file as main() */
56 # include <SDL.h>
57 # endif
58 
59 # include "../macosx/macos.h"
60 #endif
61 
62 #include "../../safeguards.h"
63 
64 bool FiosIsRoot(const char *path)
65 {
66  return path[1] == '\0';
67 }
68 
69 void FiosGetDrives(FileList &file_list)
70 {
71  return;
72 }
73 
74 bool FiosGetDiskFreeSpace(const char *path, uint64 *tot)
75 {
76  uint64 free = 0;
77 
78 #ifdef __APPLE__
79  struct statfs s;
80 
81  if (statfs(path, &s) != 0) return false;
82  free = (uint64)s.f_bsize * s.f_bavail;
83 #elif defined(HAS_STATVFS)
84  struct statvfs s;
85 
86  if (statvfs(path, &s) != 0) return false;
87  free = (uint64)s.f_frsize * s.f_bavail;
88 #endif
89  if (tot != nullptr) *tot = free;
90  return true;
91 }
92 
93 bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb)
94 {
95  char filename[MAX_PATH];
96  int res;
97  assert(path[strlen(path) - 1] == PATHSEPCHAR);
98  if (strlen(path) > 2) assert(path[strlen(path) - 2] != PATHSEPCHAR);
99  res = seprintf(filename, lastof(filename), "%s%s", path, ent->d_name);
100 
101  /* Could we fully concatenate the path and filename? */
102  if (res >= (int)lengthof(filename) || res < 0) return false;
103 
104  return stat(filename, sb) == 0;
105 }
106 
107 bool FiosIsHiddenFile(const struct dirent *ent)
108 {
109  return ent->d_name[0] == '.';
110 }
111 
112 #ifdef WITH_ICONV
113 
114 #include <iconv.h>
115 #include <errno.h>
116 #include "../../debug.h"
117 #include "../../string_func.h"
118 
119 const char *GetCurrentLocale(const char *param);
120 
121 #define INTERNALCODE "UTF-8"
122 
128 static const char *GetLocalCode()
129 {
130 #if defined(__APPLE__)
131  return "UTF-8-MAC";
132 #else
133  /* Strip locale (eg en_US.UTF-8) to only have UTF-8 */
134  const char *locale = GetCurrentLocale("LC_CTYPE");
135  if (locale != nullptr) locale = strchr(locale, '.');
136 
137  return (locale == nullptr) ? "" : locale + 1;
138 #endif
139 }
140 
145 static const char *convert_tofrom_fs(iconv_t convd, const char *name)
146 {
147  static char buf[1024];
148  /* There are different implementations of iconv. The older ones,
149  * e.g. SUSv2, pass a const pointer, whereas the newer ones, e.g.
150  * IEEE 1003.1 (2004), pass a non-const pointer. */
151 #ifdef HAVE_NON_CONST_ICONV
152  char *inbuf = const_cast<char*>(name);
153 #else
154  const char *inbuf = name;
155 #endif
156 
157  char *outbuf = buf;
158  size_t outlen = sizeof(buf) - 1;
159  size_t inlen = strlen(name);
160 
161  strecpy(outbuf, name, outbuf + outlen);
162 
163  iconv(convd, nullptr, nullptr, nullptr, nullptr);
164  if (iconv(convd, &inbuf, &inlen, &outbuf, &outlen) == (size_t)(-1)) {
165  DEBUG(misc, 0, "[iconv] error converting '%s'. Errno %d", name, errno);
166  }
167 
168  *outbuf = '\0';
169  /* FIX: invalid characters will abort conversion, but they shouldn't occur? */
170  return buf;
171 }
172 
178 const char *OTTD2FS(const char *name)
179 {
180  static iconv_t convd = (iconv_t)(-1);
181 
182  if (convd == (iconv_t)(-1)) {
183  const char *env = GetLocalCode();
184  convd = iconv_open(env, INTERNALCODE);
185  if (convd == (iconv_t)(-1)) {
186  DEBUG(misc, 0, "[iconv] conversion from codeset '%s' to '%s' unsupported", INTERNALCODE, env);
187  return name;
188  }
189  }
190 
191  return convert_tofrom_fs(convd, name);
192 }
193 
199 const char *FS2OTTD(const char *name)
200 {
201  static iconv_t convd = (iconv_t)(-1);
202 
203  if (convd == (iconv_t)(-1)) {
204  const char *env = GetLocalCode();
205  convd = iconv_open(INTERNALCODE, env);
206  if (convd == (iconv_t)(-1)) {
207  DEBUG(misc, 0, "[iconv] conversion from codeset '%s' to '%s' unsupported", env, INTERNALCODE);
208  return name;
209  }
210  }
211 
212  return convert_tofrom_fs(convd, name);
213 }
214 
215 #else
216 const char *FS2OTTD(const char *name) {return name;}
217 const char *OTTD2FS(const char *name) {return name;}
218 #endif /* WITH_ICONV */
219 
220 void ShowInfo(const char *str)
221 {
222  fprintf(stderr, "%s\n", str);
223 }
224 
225 #if !defined(__APPLE__)
226 void ShowOSErrorBox(const char *buf, bool system)
227 {
228  /* All unix systems, except OSX. Only use escape codes on a TTY. */
229  if (isatty(fileno(stderr))) {
230  fprintf(stderr, "\033[1;31mError: %s\033[0;39m\n", buf);
231  } else {
232  fprintf(stderr, "Error: %s\n", buf);
233  }
234 }
235 #endif
236 
237 #ifdef WITH_COCOA
238 void cocoaSetupAutoreleasePool();
239 void cocoaReleaseAutoreleasePool();
240 #endif
241 
242 int CDECL main(int argc, char *argv[])
243 {
244  /* Make sure our arguments contain only valid UTF-8 characters. */
245  for (int i = 0; i < argc; i++) ValidateString(argv[i]);
246 
247 #ifdef WITH_COCOA
248  cocoaSetupAutoreleasePool();
249  /* This is passed if we are launched by double-clicking */
250  if (argc >= 2 && strncmp(argv[1], "-psn", 4) == 0) {
251  argv[1] = nullptr;
252  argc = 1;
253  }
254 #endif
256 
257  SetRandomSeed(time(nullptr));
258 
259  signal(SIGPIPE, SIG_IGN);
260 
261  int ret = openttd_main(argc, argv);
262 
263 #ifdef WITH_COCOA
264  cocoaReleaseAutoreleasePool();
265 #endif
266 
267  return ret;
268 }
269 
270 #ifndef WITH_COCOA
271 bool GetClipboardContents(char *buffer, const char *last)
272 {
273 #ifdef WITH_SDL2
274  if (SDL_HasClipboardText() == SDL_FALSE) {
275  return false;
276  }
277 
278  char *clip = SDL_GetClipboardText();
279  if (clip != NULL) {
280  strecpy(buffer, clip, last);
281  SDL_free(clip);
282  return true;
283  }
284 #endif
285 
286  return false;
287 }
288 #endif
289 
290 
291 #ifndef __APPLE__
292 void OSOpenBrowser(const char *url)
293 {
294  pid_t child_pid = fork();
295  if (child_pid != 0) return;
296 
297  const char *args[3];
298  args[0] = "xdg-open";
299  args[1] = url;
300  args[2] = nullptr;
301  execvp(args[0], const_cast<char * const *>(args));
302  DEBUG(misc, 0, "Failed to open url: %s", url);
303  exit(0);
304 }
305 #endif /* __APPLE__ */
306 
307 void SetCurrentThreadName(const char *threadName) {
308 #if !defined(NO_THREADS) && defined(__GLIBC__)
309 #if __GLIBC_PREREQ(2, 12)
310  if (threadName) pthread_setname_np(pthread_self(), threadName);
311 #endif /* __GLIBC_PREREQ(2, 12) */
312 #endif /* !defined(NO_THREADS) && defined(__GLIBC__) */
313 #if defined(__APPLE__)
314  MacOSSetThreadName(threadName);
315 #endif /* defined(__APPLE__) */
316 }
int openttd_main(int argc, char *argv[])
Main entry point for this lovely game.
Definition: openttd.cpp:533
const char * FS2OTTD(const TCHAR *name)
Convert to OpenTTD&#39;s encoding from that of the local environment.
Definition: win32.cpp:558
int CDECL seprintf(char *str, const char *last, const char *format,...)
Safer implementation of snprintf; same as snprintf except:
Definition: string.cpp:407
void SetRandomSeed(uint32 seed)
(Re)set the state of the random number generators.
Definition: random_func.cpp:65
bool GetClipboardContents(char *buffer, const char *last)
Try to retrieve the current clipboard contents.
Definition: unix.cpp:271
void SetCurrentThreadName(const char *threadName)
Name the thread this function is called on for the debugger.
Definition: unix.cpp:307
#define lastof(x)
Get the last element of an fixed size array.
Definition: depend.cpp:48
static void InitialiseCrashLog()
Initialiser for crash logs; do the appropriate things so crashes are handled by our crash handler ins...
const char * GetCurrentLocale(const char *)
Determine the current user&#39;s locale.
Definition: win32.cpp:713
int main(int argc, char *argv[])
Entry point.
Definition: depend.cpp:927
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:40
const TCHAR * OTTD2FS(const char *name, bool console_cp)
Convert from OpenTTD&#39;s encoding to that of the local environment.
Definition: win32.cpp:576
#define DEBUG(name, level,...)
Output a line of debugging information.
Definition: debug.h:35
List of file information.
Definition: fios.h:112
char * strecpy(char *dst, const char *src, const char *last)
Copies characters from one buffer to another.
Definition: depend.cpp:66
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: depend.cpp:129
void ValidateString(const char *str)
Scans the string for valid characters and if it finds invalid ones, replaces them with a question mar...
Definition: string.cpp:243