OpenTTD Source  12.0-beta2
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 __EMSCRIPTEN__
32 # include <emscripten.h>
33 #endif
34 
35 #ifdef __APPLE__
36 # include <sys/mount.h>
37 #elif (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L) || defined(__GLIBC__)
38 # define HAS_STATVFS
39 #endif
40 
41 #if defined(OPENBSD) || defined(__NetBSD__) || defined(__FreeBSD__)
42 # define HAS_SYSCTL
43 #endif
44 
45 #ifdef HAS_STATVFS
46 #include <sys/statvfs.h>
47 #endif
48 
49 #ifdef HAS_SYSCTL
50 #include <sys/sysctl.h>
51 #endif
52 
53 #ifndef NO_THREADS
54 #include <pthread.h>
55 #endif
56 
57 #if defined(__APPLE__)
58 # if defined(WITH_SDL)
59  /* the mac implementation needs this file included in the same file as main() */
60 # include <SDL.h>
61 # endif
62 
63 # include "../macosx/macos.h"
64 #endif
65 
66 #include "../../safeguards.h"
67 
68 bool FiosIsRoot(const char *path)
69 {
70  return path[1] == '\0';
71 }
72 
73 void FiosGetDrives(FileList &file_list)
74 {
75  return;
76 }
77 
78 bool FiosGetDiskFreeSpace(const char *path, uint64 *tot)
79 {
80  uint64 free = 0;
81 
82 #ifdef __APPLE__
83  struct statfs s;
84 
85  if (statfs(path, &s) != 0) return false;
86  free = (uint64)s.f_bsize * s.f_bavail;
87 #elif defined(HAS_STATVFS)
88  struct statvfs s;
89 
90  if (statvfs(path, &s) != 0) return false;
91  free = (uint64)s.f_frsize * s.f_bavail;
92 #endif
93  if (tot != nullptr) *tot = free;
94  return true;
95 }
96 
97 bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb)
98 {
99  char filename[MAX_PATH];
100  int res;
101  assert(path[strlen(path) - 1] == PATHSEPCHAR);
102  if (strlen(path) > 2) assert(path[strlen(path) - 2] != PATHSEPCHAR);
103  res = seprintf(filename, lastof(filename), "%s%s", path, ent->d_name);
104 
105  /* Could we fully concatenate the path and filename? */
106  if (res >= (int)lengthof(filename) || res < 0) return false;
107 
108  return stat(filename, sb) == 0;
109 }
110 
111 bool FiosIsHiddenFile(const struct dirent *ent)
112 {
113  return ent->d_name[0] == '.';
114 }
115 
116 #ifdef WITH_ICONV
117 
118 #include <iconv.h>
119 #include <errno.h>
120 #include "../../debug.h"
121 #include "../../string_func.h"
122 
123 const char *GetCurrentLocale(const char *param);
124 
125 #define INTERNALCODE "UTF-8"
126 
132 static const char *GetLocalCode()
133 {
134 #if defined(__APPLE__)
135  return "UTF-8-MAC";
136 #else
137  /* Strip locale (eg en_US.UTF-8) to only have UTF-8 */
138  const char *locale = GetCurrentLocale("LC_CTYPE");
139  if (locale != nullptr) locale = strchr(locale, '.');
140 
141  return (locale == nullptr) ? "" : locale + 1;
142 #endif
143 }
144 
149 static const char *convert_tofrom_fs(iconv_t convd, const char *name, char *outbuf, size_t outlen)
150 {
151  /* There are different implementations of iconv. The older ones,
152  * e.g. SUSv2, pass a const pointer, whereas the newer ones, e.g.
153  * IEEE 1003.1 (2004), pass a non-const pointer. */
154 #ifdef HAVE_NON_CONST_ICONV
155  char *inbuf = const_cast<char*>(name);
156 #else
157  const char *inbuf = name;
158 #endif
159 
160  size_t inlen = strlen(name);
161  char *buf = outbuf;
162 
163  strecpy(outbuf, name, outbuf + outlen);
164 
165  iconv(convd, nullptr, nullptr, nullptr, nullptr);
166  if (iconv(convd, &inbuf, &inlen, &outbuf, &outlen) == (size_t)(-1)) {
167  Debug(misc, 0, "[iconv] error converting '{}'. Errno {}", name, errno);
168  }
169 
170  *outbuf = '\0';
171  /* FIX: invalid characters will abort conversion, but they shouldn't occur? */
172  return buf;
173 }
174 
180 std::string OTTD2FS(const std::string &name)
181 {
182  static iconv_t convd = (iconv_t)(-1);
183  char buf[1024] = {};
184 
185  if (convd == (iconv_t)(-1)) {
186  const char *env = GetLocalCode();
187  convd = iconv_open(env, INTERNALCODE);
188  if (convd == (iconv_t)(-1)) {
189  Debug(misc, 0, "[iconv] conversion from codeset '{}' to '{}' unsupported", INTERNALCODE, env);
190  return name;
191  }
192  }
193 
194  return convert_tofrom_fs(convd, name.c_str(), buf, lengthof(buf));
195 }
196 
202 std::string FS2OTTD(const std::string &name)
203 {
204  static iconv_t convd = (iconv_t)(-1);
205  char buf[1024] = {};
206 
207  if (convd == (iconv_t)(-1)) {
208  const char *env = GetLocalCode();
209  convd = iconv_open(INTERNALCODE, env);
210  if (convd == (iconv_t)(-1)) {
211  Debug(misc, 0, "[iconv] conversion from codeset '{}' to '{}' unsupported", env, INTERNALCODE);
212  return name;
213  }
214  }
215 
216  return convert_tofrom_fs(convd, name.c_str(), buf, lengthof(buf));
217 }
218 
219 #endif /* WITH_ICONV */
220 
221 void ShowInfo(const char *str)
222 {
223  fprintf(stderr, "%s\n", str);
224 }
225 
226 #if !defined(__APPLE__)
227 void ShowOSErrorBox(const char *buf, bool system)
228 {
229  /* All unix systems, except OSX. Only use escape codes on a TTY. */
230  if (isatty(fileno(stderr))) {
231  fprintf(stderr, "\033[1;31mError: %s\033[0;39m\n", buf);
232  } else {
233  fprintf(stderr, "Error: %s\n", buf);
234  }
235 }
236 #endif
237 
238 #ifdef WITH_COCOA
239 void CocoaSetupAutoreleasePool();
240 void CocoaReleaseAutoreleasePool();
241 #endif
242 
243 int CDECL main(int argc, char *argv[])
244 {
245  /* Make sure our arguments contain only valid UTF-8 characters. */
246  for (int i = 0; i < argc; i++) StrMakeValidInPlace(argv[i]);
247 
248 #ifdef WITH_COCOA
249  CocoaSetupAutoreleasePool();
250  /* This is passed if we are launched by double-clicking */
251  if (argc >= 2 && strncmp(argv[1], "-psn", 4) == 0) {
252  argv[1] = nullptr;
253  argc = 1;
254  }
255 #endif
257 
258  SetRandomSeed(time(nullptr));
259 
260  signal(SIGPIPE, SIG_IGN);
261 
262  int ret = openttd_main(argc, argv);
263 
264 #ifdef WITH_COCOA
265  CocoaReleaseAutoreleasePool();
266 #endif
267 
268  return ret;
269 }
270 
271 #ifndef WITH_COCOA
272 bool GetClipboardContents(char *buffer, const char *last)
273 {
274 #ifdef WITH_SDL2
275  if (SDL_HasClipboardText() == SDL_FALSE) {
276  return false;
277  }
278 
279  char *clip = SDL_GetClipboardText();
280  if (clip != nullptr) {
281  strecpy(buffer, clip, last);
282  SDL_free(clip);
283  return true;
284  }
285 #endif
286 
287  return false;
288 }
289 #endif
290 
291 
292 #if defined(__EMSCRIPTEN__)
293 void OSOpenBrowser(const char *url)
294 {
295  /* Implementation in pre.js */
296  EM_ASM({ if(window["openttd_open_url"]) window.openttd_open_url($0, $1) }, url, strlen(url));
297 }
298 #elif !defined( __APPLE__)
299 void OSOpenBrowser(const char *url)
300 {
301  pid_t child_pid = fork();
302  if (child_pid != 0) return;
303 
304  const char *args[3];
305  args[0] = "xdg-open";
306  args[1] = url;
307  args[2] = nullptr;
308  execvp(args[0], const_cast<char * const *>(args));
309  Debug(misc, 0, "Failed to open url: {}", url);
310  exit(0);
311 }
312 #endif /* __APPLE__ */
313 
314 void SetCurrentThreadName(const char *threadName) {
315 #if !defined(NO_THREADS) && defined(__GLIBC__)
316 #if __GLIBC_PREREQ(2, 12)
317  if (threadName) pthread_setname_np(pthread_self(), threadName);
318 #endif /* __GLIBC_PREREQ(2, 12) */
319 #endif /* !defined(NO_THREADS) && defined(__GLIBC__) */
320 #if defined(__APPLE__)
321  MacOSSetThreadName(threadName);
322 #endif /* defined(__APPLE__) */
323 }
openttd_main
int openttd_main(int argc, char *argv[])
Main entry point for this lovely game.
Definition: openttd.cpp:523
GetClipboardContents
bool GetClipboardContents(char *buffer, const char *last)
Try to retrieve the current clipboard contents.
Definition: unix.cpp:272
FileList
List of file information.
Definition: fios.h:96
SetCurrentThreadName
void SetCurrentThreadName(const char *threadName)
Name the thread this function is called on for the debugger.
Definition: unix.cpp:314
FS2OTTD
std::string FS2OTTD(const std::wstring &name)
Convert to OpenTTD's encoding from a wide string.
Definition: win32.cpp:542
StrMakeValidInPlace
void StrMakeValidInPlace(char *str, const char *last, StringValidationSettings settings)
Scans the string for invalid characters and replaces then with a question mark '?' (if not ignored).
Definition: string.cpp:255
GetCurrentLocale
const char * GetCurrentLocale(const char *)
Determine the current user's locale.
Definition: win32.cpp:609
CrashLog::InitialiseCrashLog
static void InitialiseCrashLog()
Initialiser for crash logs; do the appropriate things so crashes are handled by our crash handler ins...
Definition: crashlog_osx.cpp:254
main
int CDECL main(int argc, char *argv[])
And the main program (what else?)
Definition: settingsgen.cpp:455
SetRandomSeed
void SetRandomSeed(uint32 seed)
(Re)set the state of the random number generators.
Definition: random_func.cpp:65
seprintf
int CDECL seprintf(char *str, const char *last, const char *format,...)
Safer implementation of snprintf; same as snprintf except:
Definition: string.cpp:535
Debug
#define Debug(name, level, format_string,...)
Ouptut a line of debugging information.
Definition: debug.h:37
lengthof
#define lengthof(x)
Return the length of an fixed size array.
Definition: stdafx.h:378
strecpy
char * strecpy(char *dst, const char *src, const char *last)
Copies characters from one buffer to another.
Definition: string.cpp:112
free
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: stdafx.h:460
lastof
#define lastof(x)
Get the last element of an fixed size array.
Definition: stdafx.h:394
OTTD2FS
std::wstring OTTD2FS(const std::string &name)
Convert from OpenTTD's encoding to a wide string.
Definition: win32.cpp:560