ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/porting.C
Revision: 1.6
Committed: Tue Sep 12 23:22:32 2006 UTC (17 years, 8 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.5: +30 -37 lines
Log Message:
implement cleanup signal

File Contents

# User Rev Content
1 root 1.5
2 elmex 1.1 /*
3     * static char *rcsid_porting_c =
4 root 1.6 * "$Id: porting.C,v 1.5 2006-09-10 16:00:23 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 root 1.6 pd = STDOUT_FILENO;
184 root 1.4 else if (!strcmp (type, "w"))
185 root 1.6 pd = STDIN_FILENO;
186 root 1.4 else
187 root 1.6 return NULL;
188    
189 root 1.4 if (pipe (fd) != -1)
190     {
191     switch (fork ())
192 root 1.5 {
193 root 1.6 case -1:
194     close (fd[0]);
195     close (fd[1]);
196     break;
197     case 0:
198     close (fd[0]);
199     if ((fd[1] == pd) || (dup2 (fd[1], pd) == pd))
200     {
201     if (fd[1] != pd)
202     {
203     close (fd[1]);
204     }
205     execl ("/bin/sh", "sh", "-c", command, NULL);
206     close (pd);
207     }
208     _exit (1);
209     break;
210     default:
211     close (fd[1]);
212     if (ret = fdopen (fd[0], type))
213     {
214     return ret;
215     }
216     close (fd[0]);
217     break;
218 root 1.5 }
219 root 1.4 }
220     return NULL;
221 elmex 1.1 }
222    
223     #endif /* defined(sgi) */
224    
225    
226     /*****************************************************************************
227     * String related function
228     ****************************************************************************/
229    
230     /*
231     * A replacement of strdup(), since it's not defined at some
232     * unix variants.
233     */
234 root 1.4 char *
235     strdup_local (const char *str)
236     {
237     char *c = (char *) malloc (sizeof (char) * (strlen (str) + 1));
238 root 1.5
239 root 1.4 strcpy (c, str);
240 elmex 1.1 return c;
241     }
242    
243    
244     #define DIGIT(x) (isdigit(x) ? (x) - '0' : \
245     islower (x) ? (x) + 10 - 'a' : (x) + 10 - 'A')
246     #define MBASE ('z' - 'a' + 1 + 10)
247    
248     /* This seems to be lacking on some system */
249     #if !defined(HAVE_STRNCASECMP)
250 root 1.4 int
251     strncasecmp (const char *s1, const char *s2, int n)
252 elmex 1.1 {
253     register int c1, c2;
254    
255 root 1.4 while (*s1 && *s2 && n)
256     {
257     c1 = tolower (*s1);
258     c2 = tolower (*s2);
259     if (c1 != c2)
260 root 1.5 return (c1 - c2);
261 root 1.4 s1++;
262     s2++;
263     n--;
264     }
265 elmex 1.1 if (!n)
266 root 1.4 return (0);
267 elmex 1.1 return (int) (*s1 - *s2);
268     }
269     #endif
270    
271     #if !defined(HAVE_STRCASECMP)
272 root 1.4 int
273     strcasecmp (const char *s1, const char *s2)
274 elmex 1.1 {
275     register int c1, c2;
276    
277 root 1.4 while (*s1 && *s2)
278     {
279     c1 = tolower (*s1);
280     c2 = tolower (*s2);
281     if (c1 != c2)
282 root 1.5 return (c1 - c2);
283 root 1.4 s1++;
284     s2++;
285     }
286     if (*s1 == '\0' && *s2 == '\0')
287     return 0;
288 elmex 1.1 return (int) (*s1 - *s2);
289     }
290     #endif
291    
292 root 1.4 char *
293     strcasestr_local (const char *s, const char *find)
294 elmex 1.1 {
295 root 1.4 char c, sc;
296     size_t len;
297 elmex 1.1
298 root 1.4 if ((c = *find++) != 0)
299     {
300     c = tolower (c);
301     len = strlen (find);
302     do
303 root 1.5 {
304     do
305     {
306     if ((sc = *s++) == 0)
307     return NULL;
308     }
309     while (tolower (sc) != c);
310     }
311 root 1.4 while (strncasecmp (s, find, len) != 0);
312     s--;
313     }
314     return (char *) s;
315 elmex 1.1 }
316    
317     #if !defined(HAVE_SNPRINTF)
318    
319 root 1.4 int
320     snprintf (char *dest, int max, const char *format, ...)
321 elmex 1.1 {
322 root 1.4 va_list var;
323     int ret;
324 elmex 1.1
325 root 1.4 va_start (var, format);
326     ret = vsprintf (dest, format, var);
327     va_end (var);
328     if (ret > max)
329     abort ();
330 elmex 1.1
331 root 1.4 return ret;
332 elmex 1.1 }
333     #endif
334    
335    
336     /*
337     * Based on (n+1)^2 = n^2 + 2n + 1
338     * given that 1^2 = 1, then
339     * 2^2 = 1 + (2 + 1) = 1 + 3 = 4
340     * 3^2 = 4 + (4 + 1) = 4 + 5 = 1 + 3 + 5 = 9
341     * 4^2 = 9 + (6 + 1) = 9 + 7 = 1 + 3 + 5 + 7 = 16
342     * ...
343     * In other words, a square number can be express as the sum of the
344     * series n^2 = 1 + 3 + ... + (2n-1)
345     */
346     int
347 root 1.4 isqrt (int n)
348 elmex 1.1 {
349 root 1.4 int result, sum, prev;
350 root 1.5
351 root 1.4 result = 0;
352     prev = sum = 1;
353     while (sum <= n)
354     {
355     prev += 2;
356     sum += prev;
357     ++result;
358     }
359     return result;
360 elmex 1.1 }
361    
362    
363     /*
364     * returns a char-pointer to a static array, in which a representation
365     * of the decimal number given will be stored.
366     */
367    
368 root 1.4 char *
369     ltostr10 (signed long n)
370     {
371 root 1.5 static char buf[12]; /* maximum size is n=-2 billion, i.e. 11 characters+1
372     character for the trailing nul character */
373 root 1.4 snprintf (buf, sizeof (buf), "%ld", n);
374 elmex 1.1 return buf;
375     }
376 root 1.4
377     char *
378     doubletostr10 (double v)
379     {
380 elmex 1.1 static char tbuf[200];
381 root 1.5
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 root 1.5 close_and_delete (FILE * fp, int compressed)
406 root 1.4 {
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 root 1.5 {
429     if (mkdir (buf, SAVE_DIR_MODE))
430     {
431     LOG (llevError, "Cannot mkdir %s: %s\n", buf, strerror (errno));
432     return;
433     }
434     }
435 root 1.4 *cp = '/';
436 elmex 1.1 }
437     }