# unix.cpp

Go to the documentation of this file.

    00001 /* $Id$ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * 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.
    00006  * 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.
    00007  * 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/>.
    00008  */
    00009
    00012 #include "../../stdafx.h"
    00013 #include "../../textbuf_gui.h"
    00014 #include "../../openttd.h"
    00015 #include "../../crashlog.h"
    00016 #include "../../core/random_func.hpp"
    00017
    00018
    00019 #include <dirent.h>
    00020 #include <unistd.h>
    00021 #include <sys/stat.h>
    00022 #include <time.h>
    00023 #include <signal.h>
    00024
    00025 #ifdef __APPLE__
    00026   #include <sys/mount.h>
    00027 #elif (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L) || defined(__GLIBC__)
    00028   #define HAS_STATVFS
    00029 #endif
    00030
    00031 #ifdef HAS_STATVFS
    00032 #include <sys/statvfs.h>
    00033 #endif
    00034
    00035
    00036 #ifdef __MORPHOS__
    00037 #include <exec/types.h>
    00038 ULONG __stack = (1024*1024)*2; // maybe not that much is needed actually ;)
    00039
    00040 /* The system supplied definition of SIG_IGN does not match */
    00041 #undef SIG_IGN
    00042 #define SIG_IGN (void (*)(int))1
    00043 #endif /* __MORPHOS__ */
    00044
    00045 #ifdef __AMIGA__
    00046 #warning add stack symbol to avoid that user needs to set stack manually (tokai)
    00047 // ULONG __stack =
    00048 #endif
    00049
    00050 #if defined(__APPLE__)
    00051   #if defined(WITH_SDL)
    00052     /* the mac implementation needs this file included in the same file as main() */
    00053     #include <SDL.h>
    00054   #endif
    00055 #endif
    00056
    00057 bool FiosIsRoot(const char *path)
    00058 {
    00059 #if !defined(__MORPHOS__) && !defined(__AMIGAOS__)
    00060   return path[1] == '\0';
    00061 #else
    00062   /* On MorphOS or AmigaOS paths look like: "Volume:directory/subdirectory" */
    00063   const char *s = strchr(path, ':');
    00064   return s != NULL && s[1] == '\0';
    00065 #endif
    00066 }
    00067
    00068 void FiosGetDrives()
    00069 {
    00070   return;
    00071 }
    00072
    00073 bool FiosGetDiskFreeSpace(const char *path, uint64 *tot)
    00074 {
    00075   uint64 free = 0;
    00076
    00077 #ifdef __APPLE__
    00078   struct statfs s;
    00079
    00080   if (statfs(path, &s) != 0) return false;
    00081   free = (uint64)s.f_bsize * s.f_bavail;
    00082 #elif defined(HAS_STATVFS)
    00083   struct statvfs s;
    00084
    00085   if (statvfs(path, &s) != 0) return false;
    00086   free = (uint64)s.f_frsize * s.f_bavail;
    00087 #endif
    00088   if (tot != NULL) *tot = free;
    00089   return true;
    00090 }
    00091
    00092 bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb)
    00093 {
    00094   char filename[MAX_PATH];
    00095   int res;
    00096 #if defined(__MORPHOS__) || defined(__AMIGAOS__)
    00097   /* On MorphOS or AmigaOS paths look like: "Volume:directory/subdirectory" */
    00098   if (FiosIsRoot(path)) {
    00099     res = snprintf(filename, lengthof(filename), "%s:%s", path, ent->d_name);
    00100   } else // XXX - only next line!
    00101 #else
    00102   assert(path[strlen(path) - 1] == PATHSEPCHAR);
    00103   if (strlen(path) > 2) assert(path[strlen(path) - 2] != PATHSEPCHAR);
    00104 #endif
    00105   res = snprintf(filename, lengthof(filename), "%s%s", path, ent->d_name);
    00106
    00107   /* Could we fully concatenate the path and filename? */
    00108   if (res >= (int)lengthof(filename) || res < 0) return false;
    00109
    00110   return stat(filename, sb) == 0;
    00111 }
    00112
    00113 bool FiosIsHiddenFile(const struct dirent *ent)
    00114 {
    00115   return ent->d_name[0] == '.';
    00116 }
    00117
    00118 #ifdef WITH_ICONV
    00119
    00120 #include <iconv.h>
    00121 #include <errno.h>
    00122 #include "../../debug.h"
    00123 #include "../../string_func.h"
    00124
    00125 const char *GetCurrentLocale(const char *param);
    00126
    00127 #define INTERNALCODE "UTF-8"
    00128
    00134 static const char *GetLocalCode()
    00135 {
    00136 #if defined(__APPLE__)
    00137   return "UTF-8-MAC";
    00138 #else
    00139   /* Strip locale (eg en_US.UTF-8) to only have UTF-8 */
    00140   const char *locale = GetCurrentLocale("LC_CTYPE");
    00141   if (locale != NULL) locale = strchr(locale, '.');
    00142
    00143   return (locale == NULL) ? "" : locale + 1;
    00144 #endif
    00145 }
    00146
    00151 static const char *convert_tofrom_fs(iconv_t convd, const char *name)
    00152 {
    00153   static char buf[1024];
    00154   /* There are different implementations of iconv. The older ones,
    00155    * e.g. SUSv2, pass a const pointer, whereas the newer ones, e.g.
    00156    * IEEE 1003.1 (2004), pass a non-const pointer. */
    00157 #ifdef HAVE_NON_CONST_ICONV
    00158   char *inbuf = const_cast<char*>(name);
    00159 #else
    00160   const char *inbuf = name;
    00161 #endif
    00162
    00163   char *outbuf  = buf;
    00164   size_t outlen = sizeof(buf) - 1;
    00165   size_t inlen  = strlen(name);
    00166
    00167   strecpy(outbuf, name, outbuf + outlen);
    00168
    00169   iconv(convd, NULL, NULL, NULL, NULL);
    00170   if (iconv(convd, &inbuf, &inlen, &outbuf, &outlen) == (size_t)(-1)) {
    00171     DEBUG(misc, 0, "[iconv] error converting '%s'. Errno %d", name, errno);
    00172   }
    00173
    00174   *outbuf = '\0';
    00175   /* FIX: invalid characters will abort conversion, but they shouldn't occur? */
    00176   return buf;
    00177 }
    00178
    00184 const char *OTTD2FS(const char *name)
    00185 {
    00186   static iconv_t convd = (iconv_t)(-1);
    00187
    00188   if (convd == (iconv_t)(-1)) {
    00189     const char *env = GetLocalCode();
    00190     convd = iconv_open(env, INTERNALCODE);
    00191     if (convd == (iconv_t)(-1)) {
    00192       DEBUG(misc, 0, "[iconv] conversion from codeset '%s' to '%s' unsupported", INTERNALCODE, env);
    00193       return name;
    00194     }
    00195   }
    00196
    00197   return convert_tofrom_fs(convd, name);
    00198 }
    00199
    00205 const char *FS2OTTD(const char *name)
    00206 {
    00207   static iconv_t convd = (iconv_t)(-1);
    00208
    00209   if (convd == (iconv_t)(-1)) {
    00210     const char *env = GetLocalCode();
    00211     convd = iconv_open(INTERNALCODE, env);
    00212     if (convd == (iconv_t)(-1)) {
    00213       DEBUG(misc, 0, "[iconv] conversion from codeset '%s' to '%s' unsupported", env, INTERNALCODE);
    00214       return name;
    00215     }
    00216   }
    00217
    00218   return convert_tofrom_fs(convd, name);
    00219 }
    00220
    00221 #else
    00222 const char *FS2OTTD(const char *name) {return name;}
    00223 const char *OTTD2FS(const char *name) {return name;}
    00224 #endif /* WITH_ICONV */
    00225
    00226 void ShowInfo(const char *str)
    00227 {
    00228   fprintf(stderr, "%s\n", str);
    00229 }
    00230
    00231 #if !defined(__APPLE__)
    00232 void ShowOSErrorBox(const char *buf, bool system)
    00233 {
    00234   /* All unix systems, except OSX. Only use escape codes on a TTY. */
    00235   if (isatty(fileno(stderr))) {
    00236     fprintf(stderr, "\033[1;31mError: %s\033[0;39m\n", buf);
    00237   } else {
    00238     fprintf(stderr, "Error: %s\n", buf);
    00239   }
    00240 }
    00241 #endif
    00242
    00243 #ifdef WITH_COCOA
    00244 void cocoaSetupAutoreleasePool();
    00245 void cocoaReleaseAutoreleasePool();
    00246 #endif
    00247
    00248 int CDECL main(int argc, char *argv[])
    00249 {
    00250   int ret;
    00251
    00252 #ifdef WITH_COCOA
    00253   cocoaSetupAutoreleasePool();
    00254   /* This is passed if we are launched by double-clicking */
    00255   if (argc >= 2 && strncmp(argv[1], "-psn", 4) == 0) {
    00256     argv[1] = NULL;
    00257     argc = 1;
    00258   }
    00259 #endif
    00260   CrashLog::InitialiseCrashLog();
    00261
    00262   SetRandomSeed(time(NULL));
    00263
    00264   signal(SIGPIPE, SIG_IGN);
    00265
    00266   ret = ttd_main(argc, argv);
    00267
    00268 #ifdef WITH_COCOA
    00269   cocoaReleaseAutoreleasePool();
    00270 #endif
    00271
    00272   return ret;
    00273 }
    00274
    00275 #ifndef WITH_COCOA
    00276 bool GetClipboardContents(char *buffer, size_t buff_len)
    00277 {
    00278   return false;
    00279 }
    00280 #endif
    00281
    00282
    00283 /* multi os compatible sleep function */
    00284
    00285 #ifdef __AMIGA__
    00286 /* usleep() implementation */
    00287 # include <devices/timer.h>
    00288 # include <dos/dos.h>
    00289
    00290   extern struct Device      *TimerBase    = NULL;
    00291   extern struct MsgPort     *TimerPort    = NULL;
    00292   extern struct timerequest *TimerRequest = NULL;
    00293 #endif /* __AMIGA__ */
    00294
    00295 void CSleep(int milliseconds)
    00296 {
    00297   #if defined(PSP)
    00298     sceKernelDelayThread(milliseconds * 1000);
    00299   #elif defined(__BEOS__)
    00300     snooze(milliseconds * 1000);
    00301   #elif defined(__AMIGA__)
    00302   {
    00303     ULONG signals;
    00304     ULONG TimerSigBit = 1 << TimerPort->mp_SigBit;
    00305
    00306     /* send IORequest */
    00307     TimerRequest->tr_node.io_Command = TR_ADDREQUEST;
    00308     TimerRequest->tr_time.tv_secs    = (milliseconds * 1000) / 1000000;
    00309     TimerRequest->tr_time.tv_micro   = (milliseconds * 1000) % 1000000;
    00310     SendIO((struct IORequest *)TimerRequest);
    00311
    00312     if (!((signals = Wait(TimerSigBit | SIGBREAKF_CTRL_C)) & TimerSigBit) ) {
    00313       AbortIO((struct IORequest *)TimerRequest);
    00314     }
    00315     WaitIO((struct IORequest *)TimerRequest);
    00316   }
    00317   #else
    00318     usleep(milliseconds * 1000);
    00319   #endif
    00320 }