Atrinik Client 2.5
client/wrapper.c
Go to the documentation of this file.
00001 /************************************************************************
00002 *            Atrinik, a Multiplayer Online Role Playing Game            *
00003 *                                                                       *
00004 *    Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team    *
00005 *                                                                       *
00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game)     *
00007 * and Crossfire (Multiplayer game for X-windows).                       *
00008 *                                                                       *
00009 * This program is free software; you can redistribute it and/or modify  *
00010 * it under the terms of the GNU General Public License as published by  *
00011 * the Free Software Foundation; either version 2 of the License, or     *
00012 * (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.  See the         *
00017 * GNU General Public License for more details.                          *
00018 *                                                                       *
00019 * You should have received a copy of the GNU General Public License     *
00020 * along with this program; if not, write to the Free Software           *
00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.             *
00022 *                                                                       *
00023 * The author can be reached at admin@atrinik.org                        *
00024 ************************************************************************/
00025 
00030 #include <global.h>
00031 
00032 static FILE *logstream = NULL;
00033 
00036 static const char *const loglevel_names[] =
00037 {
00038     "[Error] ",
00039     "[Bug]   ",
00040     "[Debug] ",
00041     "[Info]  "
00042 };
00043 
00049 void LOG(LogLevel logLevel, char *format, ...)
00050 {
00051     va_list ap;
00052     char buf[HUGE_BUF * 4];
00053 
00054     if (!logstream)
00055     {
00056         logstream = fopen_wrapper(LOG_FILE, "w");
00057     }
00058 
00059     va_start(ap, format);
00060     vsnprintf(buf, sizeof(buf), format, ap);
00061     va_end(ap);
00062 
00063     fputs(loglevel_names[logLevel], stdout);
00064     fputs(buf, stdout);
00065 
00066     if (logstream)
00067     {
00068         fputs(loglevel_names[logLevel], logstream);
00069         fputs(buf, logstream);
00070         fflush(logstream);
00071     }
00072 
00073     if (logLevel == llevError)
00074     {
00075         LOG(llevInfo, "\nFatal error encountered. Exiting...\n");
00076         system_end();
00077         abort();
00078         exit(-1);
00079     }
00080 }
00081 
00084 void system_start()
00085 {
00086     SDL_Surface *icon;
00087 
00088     icon = IMG_Load_wrapper(DIRECTORY_BITMAPS"/"CLIENT_ICON_NAME);
00089 
00090     if (icon)
00091     {
00092         SDL_WM_SetIcon(icon, 0);
00093         SDL_FreeSurface(icon);
00094     }
00095 
00096     SDL_WM_SetCaption(PACKAGE_NAME, PACKAGE_NAME);
00097 
00098     logstream = fopen_wrapper(LOG_FILE, "w");
00099 }
00100 
00103 void system_end()
00104 {
00105     popup_destroy_visible();
00106     list_remove_all();
00107     script_killall();
00108     save_interface_file();
00109     kill_widgets();
00110     curl_deinit();
00111     socket_deinitialize();
00112     sound_deinit();
00113     free_bitmaps();
00114     text_deinit();
00115     free_help_files();
00116     effects_deinit();
00117     settings_deinit();
00118     keybind_deinit();
00119     SDL_Quit();
00120 }
00121 
00127 char *get_word_from_string(char *str, int *pos)
00128 {
00129     static char buf[HUGE_BUF];
00130     int i = 0;
00131 
00132     buf[0] = '\0';
00133 
00134     while (*(str + (*pos)) != '\0' && (!isalnum(*(str + (*pos))) && !isalpha(*(str + (*pos)))))
00135     {
00136         (*pos)++;
00137     }
00138 
00139     /* Nothing left */
00140     if (*(str + (*pos)) == '\0')
00141     {
00142         return NULL;
00143     }
00144 
00145     /* Copy until end of string or whitespace */
00146     while (*(str + (*pos)) != '\0' && (isalnum(*(str + (*pos))) || isalpha(*(str + (*pos)))))
00147     {
00148         buf[i++] = *(str + (*pos)++);
00149     }
00150 
00151     buf[i] = '\0';
00152 
00153     return buf;
00154 }
00155 
00162 static int mkdir_recurse(const char *path)
00163 {
00164     char *copy, *p;
00165 
00166     p = copy = strdup(path);
00167 
00168     do
00169     {
00170         p = strchr(p + 1, '/');
00171 
00172         if (p)
00173         {
00174             *p = '\0';
00175         }
00176 
00177         if (access(copy, F_OK) == -1)
00178         {
00179             if (mkdir(copy, 0755) == -1)
00180             {
00181                 free(copy);
00182                 return -1;
00183             }
00184         }
00185 
00186         if (p)
00187         {
00188             *p = '/';
00189         }
00190     }
00191     while (p);
00192 
00193     free(copy);
00194 
00195     return 0;
00196 }
00197 
00202 void copy_file(const char *filename, const char *filename_out)
00203 {
00204     FILE *fp, *fp_out;
00205     char buf[HUGE_BUF], *stmp;
00206 
00207     fp = fopen(filename, "r");
00208 
00209     if (!fp)
00210     {
00211         LOG(llevBug, "copy_file(): Failed to open '%s' for reading.\n", filename);
00212         return;
00213     }
00214 
00215     stmp = strrchr(filename_out, '/');
00216 
00217     if (stmp)
00218     {
00219         char ctmp;
00220 
00221         ctmp = stmp[0];
00222         stmp[0] = '\0';
00223         mkdir_recurse(filename_out);
00224         stmp[0] = ctmp;
00225     }
00226 
00227     fp_out = fopen(filename_out, "w");
00228 
00229     if (!fp_out)
00230     {
00231         LOG(llevBug, "copy_file(): Failed to open '%s' for writing.\n", filename_out);
00232         fclose(fp);
00233         return;
00234     }
00235 
00236     while (fgets(buf, sizeof(buf), fp))
00237     {
00238         fputs(buf, fp_out);
00239     }
00240 
00241     fclose(fp);
00242     fclose(fp_out);
00243 }
00244 
00251 void copy_if_exists(const char *from, const char *to, const char *src, const char *dst)
00252 {
00253     char src_path[HUGE_BUF], dst_path[HUGE_BUF];
00254 
00255     snprintf(src_path, sizeof(src_path), "%s/%s", from, src);
00256     snprintf(dst_path, sizeof(dst_path), "%s/%s", to, dst);
00257 
00258     if (access(src_path, R_OK) == 0)
00259     {
00260         copy_rec(src_path, dst_path);
00261     }
00262 }
00263 
00269 void rmrf(const char *path)
00270 {
00271     DIR *dir;
00272     struct dirent *currentfile;
00273     char buf[HUGE_BUF];
00274     struct stat st;
00275 
00276     dir = opendir(path);
00277 
00278     if (!dir)
00279     {
00280         return;
00281     }
00282 
00283     while ((currentfile = readdir(dir)))
00284     {
00285         if (!strcmp(currentfile->d_name, ".") || !strcmp(currentfile->d_name, ".."))
00286         {
00287             continue;
00288         }
00289 
00290         snprintf(buf, sizeof(buf), "%s/%s", path, currentfile->d_name);
00291 
00292         if (stat(buf, &st) != 0)
00293         {
00294             continue;
00295         }
00296 
00297         if (S_ISDIR(st.st_mode))
00298         {
00299             rmrf(buf);
00300         }
00301         else if (S_ISREG(st.st_mode))
00302         {
00303             unlink(buf);
00304         }
00305     }
00306 
00307     closedir(dir);
00308     rmdir(path);
00309 }
00310 
00315 void copy_rec(const char *src, const char *dst)
00316 {
00317     struct stat st;
00318 
00319     /* Does it exist? */
00320     if (stat(src, &st) != 0)
00321     {
00322         return;
00323     }
00324 
00325     /* Copy directory contents. */
00326     if (S_ISDIR(st.st_mode))
00327     {
00328         DIR *dir;
00329         struct dirent *currentfile;
00330         char dir_src[HUGE_BUF], dir_dst[HUGE_BUF];
00331 
00332         dir = opendir(src);
00333 
00334         if (!dir)
00335         {
00336             return;
00337         }
00338 
00339         /* Try to make the new directory. */
00340         if (access(dst, R_OK) != 0)
00341         {
00342             mkdir(dst, 0755);
00343         }
00344 
00345         while ((currentfile = readdir(dir)))
00346         {
00347             if (currentfile->d_name[0] == '.')
00348             {
00349                 continue;
00350             }
00351 
00352             snprintf(dir_src, sizeof(dir_src), "%s/%s", src, currentfile->d_name);
00353             snprintf(dir_dst, sizeof(dir_dst), "%s/%s", dst, currentfile->d_name);
00354             copy_rec(dir_src, dir_dst);
00355         }
00356 
00357         closedir(dir);
00358     }
00359     /* Copy file. */
00360     else
00361     {
00362         copy_file(src, dst);
00363     }
00364 }
00365 
00369 const char *get_config_dir()
00370 {
00371     const char *desc;
00372 
00373 #ifdef LINUX
00374     desc = getenv("HOME");
00375 #else
00376     desc = getenv("APPDATA");
00377 #endif
00378 
00379     /* Failed to find an usable destination, so store it in the
00380      * current directory. */
00381     if (!desc || !*desc)
00382     {
00383         desc = ".";
00384     }
00385 
00386     return desc;
00387 }
00388 
00394 void get_data_dir_file(char *buf, size_t len, const char *fname)
00395 {
00396     /* Try the current directory first. */
00397     snprintf(buf, len, "./%s", fname);
00398 
00399 #ifdef INSTALL_SUBDIR_SHARE
00400     /* Not found, try the share directory since it was defined... */
00401     if (access(buf, R_OK))
00402     {
00403         char *prefix;
00404 
00405         /* Get the prefix. */
00406         prefix = br_find_prefix("./");
00407         /* Construct the path. */
00408         snprintf(buf, len, "%s/"INSTALL_SUBDIR_SHARE"/%s", prefix, fname);
00409         free(prefix);
00410     }
00411 #endif
00412 }
00413 
00420 char *file_path(const char *fname, const char *mode)
00421 {
00422     static char tmp[HUGE_BUF];
00423     char *stmp, ctmp, version[MAX_BUF];
00424 
00425     snprintf(tmp, sizeof(tmp), "%s/.atrinik/%s/%s", get_config_dir(), package_get_version_partial(version, sizeof(version)), fname);
00426 
00427     if (strchr(mode, 'w'))
00428     {
00429         if ((stmp = strrchr(tmp, '/')))
00430         {
00431             ctmp = stmp[0];
00432             stmp[0] = '\0';
00433             mkdir_recurse(tmp);
00434             stmp[0] = ctmp;
00435         }
00436     }
00437     else if (strchr(mode, '+') || strchr(mode, 'a'))
00438     {
00439         if (access(tmp, W_OK))
00440         {
00441             char otmp[HUGE_BUF];
00442 
00443             get_data_dir_file(otmp, sizeof(otmp), fname);
00444 
00445             if ((stmp = strrchr(tmp, '/')))
00446             {
00447                 ctmp = stmp[0];
00448                 stmp[0] = '\0';
00449                 mkdir_recurse(tmp);
00450                 stmp[0] = ctmp;
00451             }
00452 
00453             copy_file(otmp, tmp);
00454         }
00455     }
00456     else
00457     {
00458         if (access(tmp, R_OK))
00459         {
00460             get_data_dir_file(tmp, sizeof(tmp), fname);
00461         }
00462     }
00463 
00464     return tmp;
00465 }
00466 
00482 FILE *fopen_wrapper(const char *fname, const char *mode)
00483 {
00484     return fopen(file_path(fname, mode), mode);
00485 }
00486 
00491 SDL_Surface *IMG_Load_wrapper(const char *file)
00492 {
00493     return IMG_Load(file_path(file, "r"));
00494 }
00495 
00501 TTF_Font *TTF_OpenFont_wrapper(const char *file, int ptsize)
00502 {
00503     return TTF_OpenFont(file_path(file, "r"), ptsize);
00504 }