ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/porting.C
Revision: 1.7
Committed: Thu Sep 14 22:34:00 2006 UTC (17 years, 8 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.6: +1 -7 lines
Log Message:
indent

File Contents

# User Rev Content
1 elmex 1.1 /*
2     CrossFire, A Multiplayer game for X-windows
3    
4     Copyright (C) 2002 Mark Wedel & Crossfire Development Team
5     Copyright (C) 1992 Frank Tore Johansen
6    
7     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11    
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     GNU General Public License for more details.
16    
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20    
21 root 1.7 The authors can be reached via e-mail at <crossfire@schmorp.de>
22 elmex 1.1 */
23    
24     /* This file contains various functions that are not really unique for
25     * crossfire, but rather provides what should be standard functions
26     * for systems that do not have them. In this way, most of the
27     * nasty system dependent stuff is contained here, with the program
28     * calling these functions.
29     */
30    
31    
32 root 1.5 #ifdef WIN32 /* ---win32 exclude/include headers */
33     # include "process.h"
34     # define pid_t int /* we include it non global, because there is a redefinition in python.h */
35 elmex 1.1 #else
36 root 1.5 # include <ctype.h>
37     # include <sys/stat.h>
38     # include <sys/wait.h>
39 elmex 1.1
40 root 1.5 # include <sys/param.h>
41     # include <stdio.h>
42 elmex 1.1
43     /* Need to pull in the HAVE_... values somehow */
44 root 1.5
45 elmex 1.1 /* win32 reminder: always put this in a ifndef win32 block */
46 root 1.5 # include <autoconf.h>
47 elmex 1.1 #endif
48    
49    
50     #ifdef HAVE_STDLIB_H
51 root 1.5 # include <stdlib.h>
52 elmex 1.1 #endif
53    
54     #ifdef HAVE_UNISTD_H
55 root 1.5 # include <unistd.h>
56 elmex 1.1 #endif
57    
58     #include <stdarg.h>
59 root 1.5
60 elmex 1.1 /* Has to be after above includes so we don't redefine some values */
61     #include "global.h"
62    
63     static unsigned int curtmp = 0;
64    
65     /*****************************************************************************
66     * File related functions
67     ****************************************************************************/
68    
69     /*
70     * A replacement for the tempnam() function since it's not defined
71     * at some unix variants.
72     */
73    
74 root 1.4 char *
75     tempnam_local (const char *dir, const char *pfx)
76 elmex 1.1 {
77 root 1.4 char *name;
78     pid_t pid = getpid ();
79 elmex 1.1
80     /* HURD does not have a hard limit, but we do */
81     #ifndef MAXPATHLEN
82 root 1.5 # define MAXPATHLEN 4096
83 elmex 1.1 #endif
84    
85 root 1.4 if (!(name = (char *) malloc (MAXPATHLEN)))
86     return (NULL);
87 elmex 1.1
88 root 1.4 if (!pfx)
89     pfx = "cftmp.";
90 elmex 1.1
91 root 1.4 /* This is a pretty simple method - put the pid as a hex digit and
92     * just keep incrementing the last digit. Check to see if the file
93     * already exists - if so, we'll just keep looking - eventually we should
94     * find one that is free.
95     */
96     if (dir != NULL)
97     {
98     do
99 root 1.5 {
100 elmex 1.1 #ifdef HAVE_SNPRINTF
101 root 1.5 (void) snprintf (name, MAXPATHLEN, "%s/%s%hx.%d", dir, pfx, pid, curtmp);
102 elmex 1.1 #else
103 root 1.5 (void) sprintf (name, "%s/%s%hx%d", dir, pfx, pid, curtmp);
104 elmex 1.1 #endif
105 root 1.5 curtmp++;
106     }
107 root 1.4 while (access (name, F_OK) != -1);
108     return (name);
109 elmex 1.1 }
110 root 1.4 return (NULL);
111 elmex 1.1 }
112    
113    
114    
115     /* This function removes everything in the directory. */
116 root 1.4 void
117     remove_directory (const char *path)
118 elmex 1.1 {
119 root 1.4 DIR *dirp;
120     char buf[MAX_BUF];
121     struct stat statbuf;
122     int status;
123    
124     if ((dirp = opendir (path)) != NULL)
125     {
126     struct dirent *de;
127    
128     for (de = readdir (dirp); de; de = readdir (dirp))
129 root 1.5 {
130     /* Don't remove '.' or '..' In theory we should do a better
131     * check for .., but the directories we are removing are fairly
132     * limited and should not have dot files in them.
133     */
134     if (de->d_name[0] == '.')
135     continue;
136    
137     /* Linux actually has a type field in the dirent structure,
138     * but that is not portable - stat should be portable
139     */
140     status = stat (de->d_name, &statbuf);
141     if ((status != -1) && (S_ISDIR (statbuf.st_mode)))
142     {
143     sprintf (buf, "%s/%s", path, de->d_name);
144     remove_directory (buf);
145     continue;
146     }
147     sprintf (buf, "%s/%s", path, de->d_name);
148     if (unlink (buf))
149     {
150     LOG (llevError, "Unable to remove directory %s\n", path);
151     }
152     }
153 root 1.4 closedir (dirp);
154     }
155     if (rmdir (path))
156     {
157     LOG (llevError, "Unable to remove directory %s\n", path);
158 elmex 1.1 }
159     }
160    
161     #if defined(sgi)
162    
163 root 1.5 # include <stdio.h>
164     # include <stdlib.h>
165     # include <string.h>
166 elmex 1.1
167 root 1.5 # define popen fixed_popen
168 elmex 1.1
169 root 1.4 FILE *
170     popen_local (const char *command, const char *type)
171 elmex 1.1 {
172 root 1.4 int fd[2];
173     int pd;
174     FILE *ret;
175 root 1.5
176 root 1.4 if (!strcmp (type, "r"))
177 root 1.6 pd = STDOUT_FILENO;
178 root 1.4 else if (!strcmp (type, "w"))
179 root 1.6 pd = STDIN_FILENO;
180 root 1.4 else
181 root 1.6 return NULL;
182    
183 root 1.4 if (pipe (fd) != -1)
184     {
185     switch (fork ())
186 root 1.5 {
187 root 1.6 case -1:
188     close (fd[0]);
189     close (fd[1]);
190     break;
191     case 0:
192     close (fd[0]);
193     if ((fd[1] == pd) || (dup2 (fd[1], pd) == pd))
194     {
195     if (fd[1] != pd)
196     {
197     close (fd[1]);
198     }
199     execl ("/bin/sh", "sh", "-c", command, NULL);
200     close (pd);
201     }
202     _exit (1);
203     break;
204     default:
205     close (fd[1]);
206     if (ret = fdopen (fd[0], type))
207     {
208     return ret;
209     }
210     close (fd[0]);
211     break;
212 root 1.5 }
213 root 1.4 }
214     return NULL;
215 elmex 1.1 }
216    
217     #endif /* defined(sgi) */
218    
219    
220     /*****************************************************************************
221     * String related function
222     ****************************************************************************/
223    
224     /*
225     * A replacement of strdup(), since it's not defined at some
226     * unix variants.
227     */
228 root 1.4 char *
229     strdup_local (const char *str)
230     {
231     char *c = (char *) malloc (sizeof (char) * (strlen (str) + 1));
232 root 1.5
233 root 1.4 strcpy (c, str);
234 elmex 1.1 return c;
235     }
236    
237    
238     #define DIGIT(x) (isdigit(x) ? (x) - '0' : \
239     islower (x) ? (x) + 10 - 'a' : (x) + 10 - 'A')
240     #define MBASE ('z' - 'a' + 1 + 10)
241    
242     /* This seems to be lacking on some system */
243     #if !defined(HAVE_STRNCASECMP)
244 root 1.4 int
245     strncasecmp (const char *s1, const char *s2, int n)
246 elmex 1.1 {
247     register int c1, c2;
248    
249 root 1.4 while (*s1 && *s2 && n)
250     {
251     c1 = tolower (*s1);
252     c2 = tolower (*s2);
253     if (c1 != c2)
254 root 1.5 return (c1 - c2);
255 root 1.4 s1++;
256     s2++;
257     n--;
258     }
259 elmex 1.1 if (!n)
260 root 1.4 return (0);
261 elmex 1.1 return (int) (*s1 - *s2);
262     }
263     #endif
264    
265     #if !defined(HAVE_STRCASECMP)
266 root 1.4 int
267     strcasecmp (const char *s1, const char *s2)
268 elmex 1.1 {
269     register int c1, c2;
270    
271 root 1.4 while (*s1 && *s2)
272     {
273     c1 = tolower (*s1);
274     c2 = tolower (*s2);
275     if (c1 != c2)
276 root 1.5 return (c1 - c2);
277 root 1.4 s1++;
278     s2++;
279     }
280     if (*s1 == '\0' && *s2 == '\0')
281     return 0;
282 elmex 1.1 return (int) (*s1 - *s2);
283     }
284     #endif
285    
286 root 1.4 char *
287     strcasestr_local (const char *s, const char *find)
288 elmex 1.1 {
289 root 1.4 char c, sc;
290     size_t len;
291 elmex 1.1
292 root 1.4 if ((c = *find++) != 0)
293     {
294     c = tolower (c);
295     len = strlen (find);
296     do
297 root 1.5 {
298     do
299     {
300     if ((sc = *s++) == 0)
301     return NULL;
302     }
303     while (tolower (sc) != c);
304     }
305 root 1.4 while (strncasecmp (s, find, len) != 0);
306     s--;
307     }
308     return (char *) s;
309 elmex 1.1 }
310    
311     #if !defined(HAVE_SNPRINTF)
312    
313 root 1.4 int
314     snprintf (char *dest, int max, const char *format, ...)
315 elmex 1.1 {
316 root 1.4 va_list var;
317     int ret;
318 elmex 1.1
319 root 1.4 va_start (var, format);
320     ret = vsprintf (dest, format, var);
321     va_end (var);
322     if (ret > max)
323     abort ();
324 elmex 1.1
325 root 1.4 return ret;
326 elmex 1.1 }
327     #endif
328    
329    
330     /*
331     * Based on (n+1)^2 = n^2 + 2n + 1
332     * given that 1^2 = 1, then
333     * 2^2 = 1 + (2 + 1) = 1 + 3 = 4
334     * 3^2 = 4 + (4 + 1) = 4 + 5 = 1 + 3 + 5 = 9
335     * 4^2 = 9 + (6 + 1) = 9 + 7 = 1 + 3 + 5 + 7 = 16
336     * ...
337     * In other words, a square number can be express as the sum of the
338     * series n^2 = 1 + 3 + ... + (2n-1)
339     */
340     int
341 root 1.4 isqrt (int n)
342 elmex 1.1 {
343 root 1.4 int result, sum, prev;
344 root 1.5
345 root 1.4 result = 0;
346     prev = sum = 1;
347     while (sum <= n)
348     {
349     prev += 2;
350     sum += prev;
351     ++result;
352     }
353     return result;
354 elmex 1.1 }
355    
356    
357     /*
358     * returns a char-pointer to a static array, in which a representation
359     * of the decimal number given will be stored.
360     */
361    
362 root 1.4 char *
363     ltostr10 (signed long n)
364     {
365 root 1.5 static char buf[12]; /* maximum size is n=-2 billion, i.e. 11 characters+1
366     character for the trailing nul character */
367 root 1.4 snprintf (buf, sizeof (buf), "%ld", n);
368 elmex 1.1 return buf;
369     }
370 root 1.4
371     char *
372     doubletostr10 (double v)
373     {
374 elmex 1.1 static char tbuf[200];
375 root 1.5
376 root 1.4 sprintf (tbuf, "%f", v);
377 elmex 1.1 return tbuf;
378     }
379    
380     /**
381     * open_and_uncompress() first searches for the original filename. If it exist,
382     * then it opens it and returns the file-pointer.
383     */
384 root 1.4 FILE *
385     open_and_uncompress (const char *name, int flag, int *compressed)
386     {
387     size_t i;
388     FILE *fp;
389 elmex 1.1
390 root 1.4 *compressed = 0;
391     return fopen (name, "r");
392 elmex 1.1 }
393    
394     /*
395     * See open_and_uncompress().
396     */
397    
398 root 1.4 void
399 root 1.5 close_and_delete (FILE * fp, int compressed)
400 root 1.4 {
401     fclose (fp);
402 elmex 1.1 }
403    
404     /*
405     * If any directories in the given path doesn't exist, they are created.
406     */
407    
408 root 1.4 void
409     make_path_to_file (char *filename)
410 elmex 1.1 {
411 root 1.4 char buf[MAX_BUF], *cp = buf;
412     struct stat statbuf;
413 elmex 1.1
414 root 1.4 if (!filename || !*filename)
415     return;
416     strcpy (buf, filename);
417    
418     while ((cp = strchr (cp + 1, (int) '/')))
419     {
420     *cp = '\0';
421     if (stat (buf, &statbuf) || !S_ISDIR (statbuf.st_mode))
422 root 1.5 {
423     if (mkdir (buf, SAVE_DIR_MODE))
424     {
425     LOG (llevError, "Cannot mkdir %s: %s\n", buf, strerror (errno));
426     return;
427     }
428     }
429 root 1.4 *cp = '/';
430 elmex 1.1 }
431     }