unix_main.c

Go to the documentation of this file.
00001 
00006 /*
00007 Copyright (C) 2002-2010 UFO: Alien Invasion.
00008 
00009 This program is free software; you can redistribute it and/or
00010 modify it under the terms of the GNU General Public License
00011 as published by the Free Software Foundation; either version 2
00012 of the License, or (at your option) any later version.
00013 
00014 This program is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00017 
00018 See the GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00023 
00024 */
00025 
00026 #include <unistd.h>
00027 #include <sys/time.h>
00028 #include <stdlib.h>
00029 #include <sys/stat.h>
00030 #include <sys/types.h>
00031 #include <pwd.h>
00032 #include <dlfcn.h>
00033 #include <fcntl.h>
00034 #include <locale.h>
00035 #include <signal.h>
00036 #include <dirent.h>
00037 
00038 #include "../../common/common.h"
00039 #include "../system.h"
00040 
00041 #ifdef HAVE_EXECINFO_H
00042 #include <execinfo.h>
00043 #define MAX_BACKTRACE_SYMBOLS 50
00044 #endif
00045 
00046 const char *Sys_GetCurrentUser (void)
00047 {
00048     static char s_userName[MAX_VAR];
00049     struct passwd *p;
00050 
00051     if ((p = getpwuid(getuid())) == NULL)
00052         s_userName[0] = '\0';
00053     else {
00054         strncpy(s_userName, p->pw_name, sizeof(s_userName));
00055         s_userName[sizeof(s_userName) - 1] = '\0';
00056     }
00057     return s_userName;
00058 }
00059 
00063 char *Sys_Cwd (void)
00064 {
00065     static char cwd[MAX_OSPATH];
00066 
00067     if (getcwd(cwd, sizeof(cwd) - 1) == NULL)
00068         return NULL;
00069     cwd[MAX_OSPATH - 1] = 0;
00070 
00071     return cwd;
00072 }
00073 
00079 void Sys_Error (const char *error, ...)
00080 {
00081     va_list argptr;
00082     char string[1024];
00083 
00084     Sys_Backtrace();
00085 
00086 #ifdef COMPILE_UFO
00087     Sys_ConsoleShutdown();
00088 #endif
00089 
00090     /* change stdin to non blocking */
00091     fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);
00092 
00093 #ifdef COMPILE_MAP
00094     Mem_Shutdown();
00095 #endif
00096 
00097     va_start(argptr,error);
00098     Q_vsnprintf(string, sizeof(string), error, argptr);
00099     va_end(argptr);
00100 
00101     fprintf(stderr, "Error: %s\n", string);
00102 
00103     exit(1);
00104 }
00105 
00110 void Sys_Quit (void)
00111 {
00112 #ifdef COMPILE_UFO
00113     CL_Shutdown();
00114     Qcommon_Shutdown();
00115     Sys_ConsoleShutdown();
00116 #elif COMPILE_MAP
00117     Mem_Shutdown();
00118 #endif
00119 
00120     fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL, 0) & ~FNDELAY);
00121     exit(0);
00122 }
00123 
00124 void Sys_Sleep (int milliseconds)
00125 {
00126 #if 0
00127     struct timespec sleep, remaining;
00128     sleep.tv_sec = (long) milliseconds / 1000;
00129     sleep.tv_nsec = 1000000 * (milliseconds - (long) milliseconds);
00130     while (nanosleep(&sleep, &remaining) < 0 && errno == EINTR)
00131         /* If nanosleep has been interrupted by a signal, adjust the
00132          * sleeping period and return to sleep.  */
00133         sleep = remaining;
00134 #endif
00135     if (milliseconds < 1)
00136         milliseconds = 1;
00137     usleep(milliseconds * 1000);
00138 }
00139 
00140 #ifdef COMPILE_UFO
00141 const char *Sys_SetLocale (const char *localeID)
00142 {
00143     const char *locale;
00144 
00145 # ifndef __sun
00146     unsetenv("LANGUAGE");
00147 # endif /* __sun */
00148 # ifdef __APPLE__
00149     if (localeID[0] != '\0') {
00150         if (Sys_Setenv("LANGUAGE", localeID) != 0)
00151             Com_Printf("...setenv for LANGUAGE failed: %s\n", localeID);
00152         if (Sys_Setenv("LC_ALL", localeID) != 0)
00153             Com_Printf("...setenv for LC_ALL failed: %s\n", localeID);
00154     }
00155 # endif /* __APPLE__ */
00156 
00157     /* set to system default */
00158     setlocale(LC_ALL, "C");
00159     locale = setlocale(LC_MESSAGES, localeID);
00160     if (!locale) {
00161         Com_DPrintf(DEBUG_CLIENT, "...could not set to language: %s\n", localeID);
00162         locale = setlocale(LC_MESSAGES, "");
00163         if (!locale) {
00164             Com_DPrintf(DEBUG_CLIENT, "...could not set to system language\n");
00165         }
00166         return NULL;
00167     } else {
00168         Com_Printf("...using language: %s\n", locale);
00169     }
00170 
00171     return locale;
00172 }
00173 
00174 const char *Sys_GetLocale (void)
00175 {
00176     /* Calling with NULL param should return current system settings. */
00177     const char *currentLocale = setlocale(LC_MESSAGES, NULL);
00178     if (currentLocale != NULL && currentLocale[0] != '\0')
00179         return currentLocale;
00180     else
00181         return "C";
00182 }
00183 #endif
00184 
00188 int Sys_Setenv (const char *name, const char *value)
00189 {
00190     if (value && value[0] != '\0')
00191         return setenv(name, value, 1);
00192     else
00193         return unsetenv(name);
00194 }
00195 
00200 char *Sys_GetHomeDirectory (void)
00201 {
00202     return getenv("HOME");
00203 }
00204 
00205 void Sys_NormPath (char* path)
00206 {
00207 }
00208 
00209 static  char    findbase[MAX_OSPATH];
00210 static  char    findpath[MAX_OSPATH];
00211 static  char    findpattern[MAX_OSPATH];
00212 static  DIR     *fdir;
00213 
00214 static qboolean CompareAttributes (const char *path, const char *name, unsigned musthave, unsigned canthave)
00215 {
00216     struct stat st;
00217     char fn[MAX_OSPATH];
00218 
00219     /* . and .. never match */
00220     if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
00221         return qfalse;
00222 
00223     Com_sprintf(fn, sizeof(fn), "%s/%s", path, name);
00224     if (stat(fn, &st) == -1) {
00225         Com_Printf("CompareAttributes: Warning, stat failed: %s\n", name);
00226         return qfalse; /* shouldn't happen */
00227     }
00228 
00229     if ((st.st_mode & S_IFDIR) && (canthave & SFF_SUBDIR))
00230         return qfalse;
00231 
00232     if ((musthave & SFF_SUBDIR) && !(st.st_mode & S_IFDIR))
00233         return qfalse;
00234 
00235     return qtrue;
00236 }
00237 
00243 char *Sys_FindFirst (const char *path, unsigned musthave, unsigned canhave)
00244 {
00245     struct dirent *d;
00246     char *p;
00247 
00248     if (fdir)
00249         Sys_Error("Sys_BeginFind without close");
00250 
00251     Q_strncpyz(findbase, path, sizeof(findbase));
00252 
00253     if ((p = strrchr(findbase, '/')) != NULL) {
00254         *p = 0;
00255         Q_strncpyz(findpattern, p + 1, sizeof(findpattern));
00256     } else
00257         Q_strncpyz(findpattern, "*", sizeof(findpattern));
00258 
00259     if (strcmp(findpattern, "*.*") == 0)
00260         Q_strncpyz(findpattern, "*", sizeof(findpattern));
00261 
00262     if ((fdir = opendir(findbase)) == NULL)
00263         return NULL;
00264 
00265     while ((d = readdir(fdir)) != NULL) {
00266         if (!*findpattern || Com_Filter(findpattern, d->d_name)) {
00267             if (CompareAttributes(findbase, d->d_name, musthave, canhave)) {
00268                 Com_sprintf(findpath, sizeof(findpath), "%s/%s", findbase, d->d_name);
00269                 return findpath;
00270             }
00271         }
00272     }
00273     return NULL;
00274 }
00275 
00282 char *Sys_FindNext (unsigned musthave, unsigned canhave)
00283 {
00284     struct dirent *d;
00285 
00286     if (fdir == NULL)
00287         return NULL;
00288     while ((d = readdir(fdir)) != NULL) {
00289         if (!*findpattern || Com_Filter(findpattern, d->d_name)) {
00290             if (CompareAttributes(findbase, d->d_name, musthave, canhave)) {
00291                 Com_sprintf(findpath, sizeof(findpath), "%s/%s", findbase, d->d_name);
00292                 return findpath;
00293             }
00294         }
00295     }
00296     return NULL;
00297 }
00298 
00299 void Sys_FindClose (void)
00300 {
00301     if (fdir != NULL)
00302         closedir(fdir);
00303     fdir = NULL;
00304 }
00305 
00306 #define MAX_FOUND_FILES 0x1000
00307 
00308 void Sys_ListFilteredFiles (const char *basedir, const char *subdirs, const char *filter, linkedList_t **list)
00309 {
00310     char search[MAX_OSPATH], newsubdirs[MAX_OSPATH];
00311     char filename[MAX_OSPATH];
00312     DIR *fdir;
00313     struct dirent *d;
00314     struct stat st;
00315 
00316     if (subdirs[0] != '\0') {
00317         Com_sprintf(search, sizeof(search), "%s/%s", basedir, subdirs);
00318     } else {
00319         Com_sprintf(search, sizeof(search), "%s", basedir);
00320     }
00321 
00322     if ((fdir = opendir(search)) == NULL)
00323         return;
00324 
00325     while ((d = readdir(fdir)) != NULL) {
00326         Com_sprintf(filename, sizeof(filename), "%s/%s", search, d->d_name);
00327         if (stat(filename, &st) == -1)
00328             continue;
00329 
00330         if (st.st_mode & S_IFDIR) {
00331             if (Q_strcasecmp(d->d_name, ".") && Q_strcasecmp(d->d_name, "..")) {
00332                 if (subdirs[0] != '\0') {
00333                     Com_sprintf(newsubdirs, sizeof(newsubdirs), "%s/%s", subdirs, d->d_name);
00334                 } else {
00335                     Com_sprintf(newsubdirs, sizeof(newsubdirs), "%s", d->d_name);
00336                 }
00337                 Sys_ListFilteredFiles(basedir, newsubdirs, filter, list);
00338             }
00339         }
00340         Com_sprintf(filename, sizeof(filename), "%s/%s", subdirs, d->d_name);
00341         if (!Com_Filter(filter, filename))
00342             continue;
00343         LIST_AddString(list, filename);
00344     }
00345 
00346     closedir(fdir);
00347 }
00348 
00349 #ifdef COMPILE_UFO
00350 void Sys_SetAffinityAndPriority (void)
00351 {
00352     if (sys_affinity->modified) {
00353         sys_affinity->modified = qfalse;
00354     }
00355 
00356     if (sys_priority->modified) {
00357         sys_priority->modified = qfalse;
00358     }
00359 }
00360 #endif
00361 
00362 int Sys_Milliseconds (void)
00363 {
00364     struct timeval tp;
00365     struct timezone tzp;
00366     static int secbase = 0;
00367 
00368     gettimeofday(&tp, &tzp);
00369 
00370     if (!secbase) {
00371         secbase = tp.tv_sec;
00372         return tp.tv_usec / 1000;
00373     }
00374 
00375     return (tp.tv_sec - secbase) * 1000 + tp.tv_usec / 1000;
00376 }
00377 
00378 void Sys_Mkdir (const char *thePath)
00379 {
00380     if (mkdir(thePath, 0777) != -1)
00381         return;
00382 
00383     if (errno != EEXIST)
00384         Com_Printf("\"mkdir %s\" failed, reason: \"%s\".", thePath, strerror(errno));
00385 }
00386 
00390 void Sys_Backtrace (void)
00391 {
00392 #ifdef HAVE_EXECINFO_H
00393     void *symbols[MAX_BACKTRACE_SYMBOLS];
00394     const int i = backtrace(symbols, MAX_BACKTRACE_SYMBOLS);
00395     backtrace_symbols_fd(symbols, i, STDERR_FILENO);
00396 #endif
00397 }
00398 
00399 #if USE_SIGNALS
00400 
00403 static void Sys_Signal (int s)
00404 {
00405     switch (s) {
00406     case SIGHUP:
00407     case SIGINT:
00408     case SIGQUIT:
00409     case SIGTERM:
00410         Com_Printf("Received signal %d, quitting..\n", s);
00411         Sys_Quit();
00412         break;
00413     default:
00414         Sys_Backtrace();
00415         Sys_Error("Received signal %d.\n", s);
00416         break;
00417     }
00418 }
00419 #endif
00420 
00421 void Sys_InitSignals (void)
00422 {
00423 #if USE_SIGNALS
00424     signal(SIGHUP, Sys_Signal);
00425     signal(SIGINT, Sys_Signal);
00426     signal(SIGQUIT, Sys_Signal);
00427     signal(SIGILL, Sys_Signal);
00428     signal(SIGABRT, Sys_Signal);
00429     signal(SIGFPE, Sys_Signal);
00430     signal(SIGSEGV, Sys_Signal);
00431     signal(SIGTERM, Sys_Signal);
00432 #endif
00433 }

Generated by  doxygen 1.6.2