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

# Content
1 /*
2 * static char *rcsid_porting_c =
3 * "$Id: porting.C,v 1.3 2006-08-30 16:30:37 root Exp $";
4 */
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 #ifdef WIN32 /* ---win32 exclude/include headers */
38 #include "process.h"
39 #define pid_t int /* we include it non global, because there is a redefinition in python.h */
40 #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 char *
78 tempnam_local (const char *dir, const char *pfx)
79 {
80 char *name;
81 pid_t pid = getpid ();
82
83 /* HURD does not have a hard limit, but we do */
84 #ifndef MAXPATHLEN
85 #define MAXPATHLEN 4096
86 #endif
87
88 if (!(name = (char *) malloc (MAXPATHLEN)))
89 return (NULL);
90
91 if (!pfx)
92 pfx = "cftmp.";
93
94 /* 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 #ifdef HAVE_SNPRINTF
104 (void) snprintf (name, MAXPATHLEN, "%s/%s%hx.%d", dir, pfx, pid, curtmp);
105 #else
106 (void) sprintf (name, "%s/%s%hx%d", dir, pfx, pid, curtmp);
107 #endif
108 curtmp++;
109 }
110 while (access (name, F_OK) != -1);
111 return (name);
112 }
113 return (NULL);
114 }
115
116
117
118 /* This function removes everything in the directory. */
119 void
120 remove_directory (const char *path)
121 {
122 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 }
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 FILE *
173 popen_local (const char *command, const char *type)
174 {
175 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 }
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 char *
238 strdup_local (const char *str)
239 {
240 char *c = (char *) malloc (sizeof (char) * (strlen (str) + 1));
241 strcpy (c, str);
242 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 int
253 strncasecmp (const char *s1, const char *s2, int n)
254 {
255 register int c1, c2;
256
257 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 if (!n)
268 return (0);
269 return (int) (*s1 - *s2);
270 }
271 #endif
272
273 #if !defined(HAVE_STRCASECMP)
274 int
275 strcasecmp (const char *s1, const char *s2)
276 {
277 register int c1, c2;
278
279 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 return (int) (*s1 - *s2);
291 }
292 #endif
293
294 char *
295 strcasestr_local (const char *s, const char *find)
296 {
297 char c, sc;
298 size_t len;
299
300 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 }
318
319 #if !defined(HAVE_SNPRINTF)
320
321 int
322 snprintf (char *dest, int max, const char *format, ...)
323 {
324 va_list var;
325 int ret;
326
327 va_start (var, format);
328 ret = vsprintf (dest, format, var);
329 va_end (var);
330 if (ret > max)
331 abort ();
332
333 return ret;
334 }
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 isqrt (int n)
350 {
351 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 }
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 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 return buf;
376 }
377
378 char *
379 doubletostr10 (double v)
380 {
381 static char tbuf[200];
382 sprintf (tbuf, "%f", v);
383 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 FILE *
391 open_and_uncompress (const char *name, int flag, int *compressed)
392 {
393 size_t i;
394 FILE *fp;
395
396 *compressed = 0;
397 return fopen (name, "r");
398 }
399
400 /*
401 * See open_and_uncompress().
402 */
403
404 void
405 close_and_delete (FILE *fp, int compressed)
406 {
407 fclose (fp);
408 }
409
410 /*
411 * If any directories in the given path doesn't exist, they are created.
412 */
413
414 void
415 make_path_to_file (char *filename)
416 {
417 char buf[MAX_BUF], *cp = buf;
418 struct stat statbuf;
419
420 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 }
437 }