ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/porting.C
Revision: 1.4
Committed: Thu Sep 7 09:28:44 2006 UTC (17 years, 8 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.3: +232 -303 lines
Log Message:
*** empty log message ***

File Contents

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