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.2 by root, Tue Aug 29 08:01:35 2006 UTC vs.
Revision 1.10 by root, Thu Dec 14 22:45:40 2006 UTC

1/*
2 * static char *rcsid_porting_c =
3 * "$Id: porting.C,v 1.2 2006/08/29 08:01:35 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/* Need to pull in the HAVE_... values somehow */
38#include "process.h" 33
39#define pid_t int /* we include it non global, because there is a redefinition in python.h */ 34#include <autoconf.h>
40#else 35
36#include <cstdio>
37#include <cstdlib>
38#include <cstdarg>
39
41#include <ctype.h> 40#include <cctype>
41
42#include <sys/stat.h> 42#include <sys/stat.h>
43#include <sys/wait.h> 43#include <sys/wait.h>
44 44
45#include <sys/param.h> 45#include <sys/param.h>
46#include <stdio.h>
47 46
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> 47#include <unistd.h>
60#endif
61 48
62#include <stdarg.h>
63/* Has to be after above includes so we don't redefine some values */ 49/* Has to be after above includes so we don't redefine some values */
64#include "global.h" 50#include "global.h"
65 51
66static unsigned int curtmp = 0; 52static unsigned int curtmp = 0;
67 53
68/* This is a list of the suffix, uncompress and compress functions. Thus,
69 * if you have some other compress program you want to use, the only thing
70 * that needs to be done is to extended this.
71 * The first entry must be NULL - this is what is used for non
72 * compressed files.
73 */
74EXTERN char *uncomp[NROF_COMPRESS_METHODS][3] = {
75 {NULL, NULL, NULL},
76 {".Z", UNCOMPRESS, COMPRESS},
77 {".gz", GUNZIP, GZIP},
78 {".bz2", BUNZIP, BZIP}
79};
80
81/*****************************************************************************
82 * File related functions
83 ****************************************************************************/
84
85/*
86 * A replacement for the tempnam() function since it's not defined
87 * at some unix variants.
88 */
89
90char *tempnam_local(const char *dir, const char *pfx)
91{
92 char *name;
93 pid_t pid=getpid();
94
95/* HURD does not have a hard limit, but we do */
96#ifndef MAXPATHLEN
97#define MAXPATHLEN 4096
98#endif
99
100 if (!(name = (char *) malloc(MAXPATHLEN)))
101 return(NULL);
102
103 if (!pfx)
104 pfx = "cftmp.";
105
106 /* This is a pretty simple method - put the pid as a hex digit and
107 * just keep incrementing the last digit. Check to see if the file
108 * already exists - if so, we'll just keep looking - eventually we should
109 * find one that is free.
110 */
111 if (dir!=NULL) {
112 do {
113#ifdef HAVE_SNPRINTF
114 (void)snprintf(name, MAXPATHLEN, "%s/%s%hx.%d", dir, pfx, pid, curtmp);
115#else
116 (void)sprintf(name,"%s/%s%hx%d", dir, pfx, pid, curtmp);
117#endif
118 curtmp++;
119 } while (access(name, F_OK)!=-1);
120 return(name);
121 }
122 return(NULL);
123}
124
125
126
127/* This function removes everything in the directory. */ 54/* This function removes everything in the directory. */
55void
128void remove_directory(const char *path) 56remove_directory (const char *path)
129{ 57{
130 DIR *dirp; 58 DIR *dirp;
131 char buf[MAX_BUF]; 59 char buf[MAX_BUF];
132 struct stat statbuf; 60 struct stat statbuf;
133 int status; 61 int status;
134 62
135 if ((dirp=opendir(path))!=NULL) { 63 if ((dirp = opendir (path)) != NULL)
64 {
136 struct dirent *de; 65 struct dirent *de;
137 66
138 for (de=readdir(dirp); de; de = readdir(dirp)) { 67 for (de = readdir (dirp); de; de = readdir (dirp))
68 {
139 /* Don't remove '.' or '..' In theory we should do a better 69 /* Don't remove '.' or '..' In theory we should do a better
140 * check for .., but the directories we are removing are fairly 70 * check for .., but the directories we are removing are fairly
141 * limited and should not have dot files in them. 71 * limited and should not have dot files in them.
142 */ 72 */
143 if (de->d_name[0] == '.') continue; 73 if (de->d_name[0] == '.')
74 continue;
144 75
145 /* Linux actually has a type field in the dirent structure, 76 /* Linux actually has a type field in the dirent structure,
146 * but that is not portable - stat should be portable 77 * but that is not portable - stat should be portable
147 */ 78 */
148 status=stat(de->d_name, &statbuf); 79 status = stat (de->d_name, &statbuf);
149 if ((status!=-1) && (S_ISDIR(statbuf.st_mode))) { 80 if ((status != -1) && (S_ISDIR (statbuf.st_mode)))
81 {
150 sprintf(buf,"%s/%s", path, de->d_name); 82 sprintf (buf, "%s/%s", path, de->d_name);
151 remove_directory(buf); 83 remove_directory (buf);
152 continue; 84 continue;
153 } 85 }
154 sprintf(buf,"%s/%s", path, de->d_name); 86 sprintf (buf, "%s/%s", path, de->d_name);
155 if (unlink(buf)) { 87 if (unlink (buf))
88 {
156 LOG(llevError,"Unable to remove directory %s\n", path); 89 LOG (llevError, "Unable to remove directory %s\n", path);
157 } 90 }
158 } 91 }
159 closedir(dirp); 92 closedir (dirp);
160 } 93 }
161 if (rmdir(path)) { 94 if (rmdir (path))
95 {
162 LOG(llevError,"Unable to remove directory %s\n", path); 96 LOG (llevError, "Unable to remove directory %s\n", path);
163 } 97 }
164} 98}
165
166#if defined(sgi)
167
168#include <stdio.h>
169#include <stdlib.h>
170#include <string.h>
171
172#define popen fixed_popen
173
174FILE *popen_local(const char *command, const char *type)
175{
176 int fd[2];
177 int pd;
178 FILE *ret;
179 if (!strcmp(type,"r"))
180 {
181 pd=STDOUT_FILENO;
182 }
183 else if (!strcmp(type,"w"))
184 {
185 pd=STDIN_FILENO;
186 }
187 else
188 {
189 return NULL;
190 }
191 if (pipe(fd)!=-1)
192 {
193 switch (fork())
194 {
195 case -1:
196 close(fd[0]);
197 close(fd[1]);
198 break;
199 case 0:
200 close(fd[0]);
201 if ((fd[1]==pd)||(dup2(fd[1],pd)==pd))
202 {
203 if (fd[1]!=pd)
204 {
205 close(fd[1]);
206 }
207 execl("/bin/sh","sh","-c",command,NULL);
208 close(pd);
209 }
210 exit(1);
211 break;
212 default:
213 close(fd[1]);
214 if (ret=fdopen(fd[0],type))
215 {
216 return ret;
217 }
218 close(fd[0]);
219 break;
220 }
221 }
222 return NULL;
223}
224
225#endif /* defined(sgi) */
226
227
228/*****************************************************************************
229 * String related function
230 ****************************************************************************/
231
232
233
234/*
235 * A replacement of strdup(), since it's not defined at some
236 * unix variants.
237 */
238char *strdup_local(const char *str) {
239 char *c=(char *)malloc(sizeof(char)*(strlen(str)+1));
240 strcpy(c,str);
241 return c;
242}
243
244 99
245#define DIGIT(x) (isdigit(x) ? (x) - '0' : \ 100#define DIGIT(x) (isdigit(x) ? (x) - '0' : \
246islower (x) ? (x) + 10 - 'a' : (x) + 10 - 'A') 101islower (x) ? (x) + 10 - 'a' : (x) + 10 - 'A')
247#define MBASE ('z' - 'a' + 1 + 10) 102#define MBASE ('z' - 'a' + 1 + 10)
248 103
249/* This seems to be lacking on some system */ 104char *
250#if !defined(HAVE_STRNCASECMP)
251int strncasecmp(const char *s1, const char *s2, int n)
252{
253 register int c1, c2;
254
255 while (*s1 && *s2 && n) {
256 c1 = tolower(*s1);
257 c2 = tolower(*s2);
258 if (c1 != c2)
259 return (c1 - c2);
260 s1++;
261 s2++;
262 n--;
263 }
264 if (!n)
265 return(0);
266 return (int) (*s1 - *s2);
267}
268#endif
269
270#if !defined(HAVE_STRCASECMP)
271int strcasecmp(const char *s1, const char*s2)
272{
273 register int c1, c2;
274
275 while (*s1 && *s2) {
276 c1 = tolower(*s1);
277 c2 = tolower(*s2);
278 if (c1 != c2)
279 return (c1 - c2);
280 s1++;
281 s2++;
282 }
283 if (*s1=='\0' && *s2=='\0')
284 return 0;
285 return (int) (*s1 - *s2);
286}
287#endif
288
289char *strcasestr_local(const char *s, const char *find) 105strcasestr_local (const char *s, const char *find)
290{ 106{
291 char c, sc; 107 char c, sc;
292 size_t len; 108 size_t len;
293 109
294 if ((c = *find++) != 0) { 110 if ((c = *find++) != 0)
111 {
295 c = tolower(c); 112 c = tolower (c);
296 len = strlen(find); 113 len = strlen (find);
114 do
297 do { 115 {
116 do
298 do { 117 {
299 if ((sc = *s++) == 0) 118 if ((sc = *s++) == 0)
300 return NULL; 119 return NULL;
120 }
301 } while (tolower(sc) != c); 121 while (tolower (sc) != c);
122 }
302 } while (strncasecmp(s, find, len) != 0); 123 while (strncasecmp (s, find, len) != 0);
303 s--; 124 s--;
304 } 125 }
305 return (char *)s; 126 return (char *) s;
306}
307
308#if !defined(HAVE_SNPRINTF)
309
310int snprintf(char *dest, int max, const char *format, ...)
311{
312 va_list var;
313 int ret;
314
315 va_start(var, format);
316 ret = vsprintf(dest, format, var);
317 va_end(var);
318 if (ret > max) abort();
319
320 return ret;
321}
322#endif
323
324
325/* This takes an err number and returns a string with a description of
326 * the error.
327 */
328char *strerror_local(int errnum)
329{
330#if defined(HAVE_STRERROR)
331 return(strerror(errnum));
332#else
333 return("strerror_local not implemented");
334#endif
335} 127}
336 128
337/* 129/*
338 * Based on (n+1)^2 = n^2 + 2n + 1 130 * Based on (n+1)^2 = n^2 + 2n + 1
339 * given that 1^2 = 1, then 131 * given that 1^2 = 1, then
343 * ... 135 * ...
344 * In other words, a square number can be express as the sum of the 136 * In other words, a square number can be express as the sum of the
345 * series n^2 = 1 + 3 + ... + (2n-1) 137 * series n^2 = 1 + 3 + ... + (2n-1)
346 */ 138 */
347int 139int
348isqrt(int n) 140isqrt (int n)
349{ 141{
350 int result, sum, prev; 142 int result, sum, prev;
143
351 result = 0; 144 result = 0;
352 prev = sum = 1; 145 prev = sum = 1;
353 while (sum <= n) { 146 while (sum <= n)
147 {
354 prev += 2; 148 prev += 2;
355 sum += prev; 149 sum += prev;
356 ++result; 150 ++result;
357 } 151 }
358 return result; 152 return result;
359} 153}
360
361 154
362/* 155/*
363 * returns a char-pointer to a static array, in which a representation 156 * returns a char-pointer to a static array, in which a representation
364 * of the decimal number given will be stored. 157 * of the decimal number given will be stored.
365 */ 158 */
366 159char *
367char *ltostr10(signed long n) { 160ltostr10 (signed long n)
161{
368 static char buf[12]; /* maximum size is n=-2 billion, i.e. 11 characters+1 162 static char buf[12]; /* maximum size is n=-2 billion, i.e. 11 characters+1
369 character for the trailing nul character */ 163 character for the trailing nul character */
370 snprintf(buf, sizeof(buf), "%ld", n); 164 snprintf (buf, sizeof (buf), "%ld", n);
371 return buf; 165 return buf;
372} 166}
167
168char *
373char *doubletostr10(double v){ 169doubletostr10 (double v)
170{
374 static char tbuf[200]; 171 static char tbuf[200];
172
375 sprintf(tbuf,"%f",v); 173 sprintf (tbuf, "%f", v);
376 return tbuf; 174 return tbuf;
377}
378
379/*
380 * A fast routine which appends the name and decimal number specified
381 * to the given buffer.
382 * Could be faster, though, if the strcat()s at the end could be changed
383 * into alternate strcat which returned a pointer to the _end_, not the
384 * start!
385 *
386 * Hey good news, it IS faster now, according to changes in get_ob_diff
387 * Completly redone prototype and made define in loader.l. See changes there.
388 * Didn't touch those for speed reason (don't use them anymore) .
389 * Tchize
390 */
391
392void save_long(char *buf, char *name, long n) {
393 char buf2[MAX_BUF];
394 strcpy(buf2,name);
395 strcat(buf2," ");
396 strcat(buf2,ltostr10(n));
397 strcat(buf2,"\n");
398 strcat(buf,buf2);
399}
400
401
402
403void save_long_long(char *buf, char *name, sint64 n) {
404 char buf2[MAX_BUF];
405
406#ifndef WIN32
407 sprintf(buf2,"%s %lld\n", name, n);
408#else
409 sprintf(buf2,"%s %I64d\n", name, n);
410#endif
411 strcat(buf,buf2);
412}
413
414/**
415 * Open and possibly uncompress a file.
416 *
417 * @param ext the extension if the file is compressed.
418 *
419 * @param uncompressor the command to uncompress the file if the file is
420 * compressed.
421 *
422 * @param name the base file name without compression extension
423 *
424 * @param flag only used for compressed files: if set, uncompress and open the
425 * file; if unset, uncompress the file via pipe
426 *
427 * @param *compressed set to zero if the file was uncompressed
428 */
429static FILE *open_and_uncompress_file(const char *ext, const char *uncompressor, const char *name, int flag, int *compressed) {
430 struct stat st;
431 char buf[MAX_BUF];
432 char buf2[MAX_BUF];
433 int ret;
434
435 if (ext == NULL) {
436 ext = "";
437 }
438
439 if (strlen(name)+strlen(ext) >= sizeof(buf)) {
440 errno = ENAMETOOLONG; /* File name too long */
441 return NULL;
442 }
443 sprintf(buf, "%s%s", name, ext);
444
445 if (stat(buf, &st) != 0) {
446 return NULL;
447 }
448
449 if (!S_ISREG(st.st_mode)) {
450 errno = EISDIR; /* Not a regular file */
451 return NULL;
452 }
453
454 if (uncompressor == NULL) {
455 /* open without uncompression */
456
457 return fopen(buf, "r");
458 }
459
460 /* The file name buf (and its substring name) is passed as an argument to a
461 * shell command, therefore check for characters that could confuse the
462 * shell.
463 */
464 if (strpbrk(buf, "'\\\r\n") != NULL) {
465 errno = ENOENT; /* Pretend the file does not exist */
466 return NULL;
467 }
468
469 if (!flag) {
470 /* uncompress via pipe */
471
472 if (strlen(uncompressor)+4+strlen(buf)+1 >= sizeof(buf2)) {
473 errno = ENAMETOOLONG; /* File name too long */
474 return NULL;
475 }
476 sprintf(buf2, "%s < '%s'", uncompressor, buf);
477
478 return popen(buf2, "r");
479 }
480
481 /* remove compression from file, then open file */
482
483 if (stat(name, &st) == 0 && !S_ISREG(st.st_mode)) {
484 errno = EISDIR;
485 return NULL;
486 }
487
488 if (strlen(uncompressor)+4+strlen(buf)+5+strlen(name)+1 >= sizeof(buf2)) {
489 errno = ENAMETOOLONG; /* File name too long */
490 return NULL;
491 }
492 sprintf(buf2, "%s < '%s' > '%s'", uncompressor, buf, name);
493
494 ret = system(buf2);
495 if (!WIFEXITED(ret) || WEXITSTATUS(ret) != 0) {
496 LOG(llevError, "system(%s) returned %d\n", buf2, ret);
497 errno = ENOENT;
498 return NULL;
499 }
500
501 unlink(buf); /* Delete the original */
502 *compressed = 0; /* Change to "uncompressed file" */
503 chmod(name, st.st_mode); /* Copy access mode from compressed file */
504
505 return fopen(name, "r");
506} 175}
507 176
508/** 177/**
509 * open_and_uncompress() first searches for the original filename. If it exist, 178 * open_and_uncompress() first searches for the original filename. If it exist,
510 * then it opens it and returns the file-pointer. 179 * then it opens it and returns the file-pointer.
511 * 180 */
512 * If not, it does two things depending on the flag. If the flag is set, it 181FILE *
513 * tries to create the original file by appending a compression suffix to name
514 * and uncompressing it. If the flag is not set, it creates a pipe that is used
515 * for reading the file (NOTE - you can not use fseek on pipes).
516 *
517 * The compressed pointer is set to nonzero if the file is compressed (and
518 * thus, fp is actually a pipe.) It returns 0 if it is a normal file.
519 */
520FILE *open_and_uncompress(const char *name, int flag, int *compressed) { 182open_and_uncompress (const char *name, int flag, int *compressed)
521 size_t i; 183{
522 FILE *fp;
523
524 for (i = 0; i < NROF_COMPRESS_METHODS; i++) {
525 *compressed = i; 184 *compressed = 0;
526 fp = open_and_uncompress_file(uncomp[i][0], uncomp[i][1], name, flag, compressed); 185 return fopen (name, "r");
527 if (fp != NULL) { 186}
187
188/*
189 * See open_and_uncompress().
190 */
191
192void
193close_and_delete (FILE * fp, int compressed)
194{
195 fclose (fp);
196}
197
198/*
199 * If any directories in the given path doesn't exist, they are created.
200 */
201
202void
203make_path_to_file (char *filename)
204{
205 char buf[MAX_BUF], *cp = buf;
206 struct stat statbuf;
207
208 if (!filename || !*filename)
209 return;
210 strcpy (buf, filename);
211
212 while ((cp = strchr (cp + 1, (int) '/')))
213 {
214 *cp = '\0';
215 if (stat (buf, &statbuf) || !S_ISDIR (statbuf.st_mode))
216 {
217 if (mkdir (buf, SAVE_DIR_MODE))
218 {
219 LOG (llevError, "Cannot mkdir %s: %s\n", buf, strerror (errno));
528 return fp; 220 return;
221 }
529 } 222 }
530 }
531
532 errno = ENOENT;
533 return NULL;
534}
535
536/*
537 * See open_and_uncompress().
538 */
539
540void close_and_delete(FILE *fp, int compressed) {
541 if (compressed)
542 pclose(fp);
543 else
544 fclose(fp);
545}
546
547/*
548 * If any directories in the given path doesn't exist, they are created.
549 */
550
551void make_path_to_file (char *filename)
552{
553 char buf[MAX_BUF], *cp = buf;
554 struct stat statbuf;
555
556 if (!filename || !*filename)
557 return;
558 strcpy (buf, filename);
559
560 while ((cp = strchr (cp + 1, (int) '/'))) {
561 *cp = '\0';
562 if (stat(buf, &statbuf) || !S_ISDIR (statbuf.st_mode)) {
563 if (mkdir (buf, SAVE_DIR_MODE)) {
564 LOG(llevError, "Cannot mkdir %s: %s\n", buf, strerror_local(errno));
565 return;
566 }
567 }
568 *cp = '/'; 223 *cp = '/';
569 } 224 }
570} 225}
571

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines