ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/porting.C
(Generate patch)

Comparing deliantra/server/common/porting.C (file contents):
Revision 1.3 by root, Wed Aug 30 16:30:37 2006 UTC vs.
Revision 1.8 by pippijn, Sat Dec 9 17:28:37 2006 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines