ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/porting.C
Revision: 1.5
Committed: Sun Sep 10 16:00:23 2006 UTC (17 years, 8 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.4: +100 -93 lines
Log Message:
indent

File Contents

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