/* * static char *rcsid_porting_c = * "$Id: porting.C,v 1.6 2006/09/12 23:22:32 root Exp $"; */ /* CrossFire, A Multiplayer game for X-windows Copyright (C) 2002 Mark Wedel & Crossfire Development Team Copyright (C) 1992 Frank Tore Johansen This program 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; either version 2 of the License, or (at your option) any later version. This program 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. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. The authors can be reached via e-mail at crossfire-devel@real-time.com */ /* This file contains various functions that are not really unique for * crossfire, but rather provides what should be standard functions * for systems that do not have them. In this way, most of the * nasty system dependent stuff is contained here, with the program * calling these functions. */ #ifdef WIN32 /* ---win32 exclude/include headers */ # include "process.h" # define pid_t int /* we include it non global, because there is a redefinition in python.h */ #else # include # include # include # include # include /* Need to pull in the HAVE_... values somehow */ /* win32 reminder: always put this in a ifndef win32 block */ # include #endif #ifdef HAVE_STDLIB_H # include #endif #ifdef HAVE_UNISTD_H # include #endif #include /* Has to be after above includes so we don't redefine some values */ #include "global.h" static unsigned int curtmp = 0; /***************************************************************************** * File related functions ****************************************************************************/ /* * A replacement for the tempnam() function since it's not defined * at some unix variants. */ char * tempnam_local (const char *dir, const char *pfx) { char *name; pid_t pid = getpid (); /* HURD does not have a hard limit, but we do */ #ifndef MAXPATHLEN # define MAXPATHLEN 4096 #endif if (!(name = (char *) malloc (MAXPATHLEN))) return (NULL); if (!pfx) pfx = "cftmp."; /* This is a pretty simple method - put the pid as a hex digit and * just keep incrementing the last digit. Check to see if the file * already exists - if so, we'll just keep looking - eventually we should * find one that is free. */ if (dir != NULL) { do { #ifdef HAVE_SNPRINTF (void) snprintf (name, MAXPATHLEN, "%s/%s%hx.%d", dir, pfx, pid, curtmp); #else (void) sprintf (name, "%s/%s%hx%d", dir, pfx, pid, curtmp); #endif curtmp++; } while (access (name, F_OK) != -1); return (name); } return (NULL); } /* This function removes everything in the directory. */ void remove_directory (const char *path) { DIR *dirp; char buf[MAX_BUF]; struct stat statbuf; int status; if ((dirp = opendir (path)) != NULL) { struct dirent *de; for (de = readdir (dirp); de; de = readdir (dirp)) { /* Don't remove '.' or '..' In theory we should do a better * check for .., but the directories we are removing are fairly * limited and should not have dot files in them. */ if (de->d_name[0] == '.') continue; /* Linux actually has a type field in the dirent structure, * but that is not portable - stat should be portable */ status = stat (de->d_name, &statbuf); if ((status != -1) && (S_ISDIR (statbuf.st_mode))) { sprintf (buf, "%s/%s", path, de->d_name); remove_directory (buf); continue; } sprintf (buf, "%s/%s", path, de->d_name); if (unlink (buf)) { LOG (llevError, "Unable to remove directory %s\n", path); } } closedir (dirp); } if (rmdir (path)) { LOG (llevError, "Unable to remove directory %s\n", path); } } #if defined(sgi) # include # include # include # define popen fixed_popen FILE * popen_local (const char *command, const char *type) { int fd[2]; int pd; FILE *ret; if (!strcmp (type, "r")) pd = STDOUT_FILENO; else if (!strcmp (type, "w")) pd = STDIN_FILENO; else return NULL; if (pipe (fd) != -1) { switch (fork ()) { case -1: close (fd[0]); close (fd[1]); break; case 0: close (fd[0]); if ((fd[1] == pd) || (dup2 (fd[1], pd) == pd)) { if (fd[1] != pd) { close (fd[1]); } execl ("/bin/sh", "sh", "-c", command, NULL); close (pd); } _exit (1); break; default: close (fd[1]); if (ret = fdopen (fd[0], type)) { return ret; } close (fd[0]); break; } } return NULL; } #endif /* defined(sgi) */ /***************************************************************************** * String related function ****************************************************************************/ /* * A replacement of strdup(), since it's not defined at some * unix variants. */ char * strdup_local (const char *str) { char *c = (char *) malloc (sizeof (char) * (strlen (str) + 1)); strcpy (c, str); return c; } #define DIGIT(x) (isdigit(x) ? (x) - '0' : \ islower (x) ? (x) + 10 - 'a' : (x) + 10 - 'A') #define MBASE ('z' - 'a' + 1 + 10) /* This seems to be lacking on some system */ #if !defined(HAVE_STRNCASECMP) int strncasecmp (const char *s1, const char *s2, int n) { register int c1, c2; while (*s1 && *s2 && n) { c1 = tolower (*s1); c2 = tolower (*s2); if (c1 != c2) return (c1 - c2); s1++; s2++; n--; } if (!n) return (0); return (int) (*s1 - *s2); } #endif #if !defined(HAVE_STRCASECMP) int strcasecmp (const char *s1, const char *s2) { register int c1, c2; while (*s1 && *s2) { c1 = tolower (*s1); c2 = tolower (*s2); if (c1 != c2) return (c1 - c2); s1++; s2++; } if (*s1 == '\0' && *s2 == '\0') return 0; return (int) (*s1 - *s2); } #endif char * strcasestr_local (const char *s, const char *find) { char c, sc; size_t len; if ((c = *find++) != 0) { c = tolower (c); len = strlen (find); do { do { if ((sc = *s++) == 0) return NULL; } while (tolower (sc) != c); } while (strncasecmp (s, find, len) != 0); s--; } return (char *) s; } #if !defined(HAVE_SNPRINTF) int snprintf (char *dest, int max, const char *format, ...) { va_list var; int ret; va_start (var, format); ret = vsprintf (dest, format, var); va_end (var); if (ret > max) abort (); return ret; } #endif /* * Based on (n+1)^2 = n^2 + 2n + 1 * given that 1^2 = 1, then * 2^2 = 1 + (2 + 1) = 1 + 3 = 4 * 3^2 = 4 + (4 + 1) = 4 + 5 = 1 + 3 + 5 = 9 * 4^2 = 9 + (6 + 1) = 9 + 7 = 1 + 3 + 5 + 7 = 16 * ... * In other words, a square number can be express as the sum of the * series n^2 = 1 + 3 + ... + (2n-1) */ int isqrt (int n) { int result, sum, prev; result = 0; prev = sum = 1; while (sum <= n) { prev += 2; sum += prev; ++result; } return result; } /* * returns a char-pointer to a static array, in which a representation * of the decimal number given will be stored. */ char * ltostr10 (signed long n) { static char buf[12]; /* maximum size is n=-2 billion, i.e. 11 characters+1 character for the trailing nul character */ snprintf (buf, sizeof (buf), "%ld", n); return buf; } char * doubletostr10 (double v) { static char tbuf[200]; sprintf (tbuf, "%f", v); return tbuf; } /** * open_and_uncompress() first searches for the original filename. If it exist, * then it opens it and returns the file-pointer. */ FILE * open_and_uncompress (const char *name, int flag, int *compressed) { size_t i; FILE *fp; *compressed = 0; return fopen (name, "r"); } /* * See open_and_uncompress(). */ void close_and_delete (FILE * fp, int compressed) { fclose (fp); } /* * If any directories in the given path doesn't exist, they are created. */ void make_path_to_file (char *filename) { char buf[MAX_BUF], *cp = buf; struct stat statbuf; if (!filename || !*filename) return; strcpy (buf, filename); while ((cp = strchr (cp + 1, (int) '/'))) { *cp = '\0'; if (stat (buf, &statbuf) || !S_ISDIR (statbuf.st_mode)) { if (mkdir (buf, SAVE_DIR_MODE)) { LOG (llevError, "Cannot mkdir %s: %s\n", buf, strerror (errno)); return; } } *cp = '/'; } }