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