ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/porting.C
Revision: 1.9
Committed: Mon Dec 11 19:46:46 2006 UTC (17 years, 5 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.8: +6 -12 lines
Log Message:
removed #ifn?def WIN32 from all files

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