ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/utils.C
Revision: 1.93
Committed: Wed Nov 4 00:02:48 2009 UTC (14 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_90
Changes since 1.92: +1 -328 lines
Log Message:
agpl reorganisation

File Contents

# User Rev Content
1 elmex 1.1 /*
2 root 1.68 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 pippijn 1.39 *
4 root 1.93 * Copyright (©) 2005,2006,2007,2008,2009 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 pippijn 1.39 *
6 root 1.89 * Deliantra is free software: you can redistribute it and/or modify it under
7     * the terms of the Affero GNU General Public License as published by the
8     * Free Software Foundation, either version 3 of the License, or (at your
9     * option) any later version.
10 pippijn 1.39 *
11 root 1.60 * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15 pippijn 1.39 *
16 root 1.89 * You should have received a copy of the Affero GNU General Public License
17     * and the GNU General Public License along with this program. If not, see
18     * <http://www.gnu.org/licenses/>.
19 root 1.57 *
20 root 1.68 * The authors can be reached via e-mail to <support@deliantra.net>
21 pippijn 1.39 */
22 elmex 1.1
23     /*
24 root 1.92 * General convenience functions for deliantra.
25 elmex 1.1 */
26    
27 root 1.37 #include <cstdlib>
28     #include <sys/types.h>
29     #include <unistd.h>
30     #include <sys/time.h>
31     #include <time.h>
32     #include <signal.h>
33    
34 elmex 1.1 #include <global.h>
35     #include <material.h>
36 sf-marcmagus 1.87 #include <object.h>
37 elmex 1.1
38 root 1.79 #include <sys/time.h>
39     #include <sys/resource.h>
40    
41 root 1.4 #include <glib.h>
42    
43 root 1.63 refcnt_base::refcnt_t refcnt_dummy;
44 root 1.74 ssize_t slice_alloc;
45 root 1.77 rand_gen rndm, rmg_rndm;
46 root 1.40
47 root 1.42 void
48     tausworthe_random_generator::seed (uint32_t seed)
49 root 1.40 {
50 root 1.74 state [0] = seed * 69069U; if (state [0] < 2U) state [0] += 2U;
51     state [1] = state [0] * 69069U; if (state [0] < 8U) state [0] += 8U;
52     state [2] = state [1] * 69069U; if (state [0] < 16U) state [0] += 16U;
53     state [3] = state [2] * 69069U; if (state [0] < 128U) state [0] += 128U;
54 root 1.40
55     for (int i = 11; --i; )
56 root 1.84 next ();
57 root 1.40 }
58    
59     uint32_t
60     tausworthe_random_generator::next ()
61     {
62     state [0] = ((state [0] & 0xFFFFFFFEU) << 18U) ^ (((state [0] << 6U) ^ state [0]) >> 13U);
63     state [1] = ((state [1] & 0xFFFFFFF8U) << 2U) ^ (((state [1] << 2U) ^ state [1]) >> 27U);
64     state [2] = ((state [2] & 0xFFFFFFF0U) << 7U) ^ (((state [2] << 13U) ^ state [2]) >> 21U);
65     state [3] = ((state [3] & 0xFFFFFF80U) << 13U) ^ (((state [3] << 3U) ^ state [3]) >> 12U);
66    
67     return state [0] ^ state [1] ^ state [2] ^ state [3];
68     }
69    
70 root 1.84 template<class generator>
71 root 1.42 uint32_t
72 root 1.84 random_number_generator<generator>::get_range (uint32_t num)
73 root 1.42 {
74 root 1.84 return (this->next () * (uint64_t)num) >> 32U;
75 root 1.42 }
76    
77     // return a number within (min .. max)
78 root 1.84 template<class generator>
79 root 1.42 int
80 root 1.84 random_number_generator<generator>::get_range (int r_min, int r_max)
81 root 1.42 {
82 root 1.50 return r_min + get_range (max (r_max - r_min + 1, 0));
83 root 1.42 }
84    
85 root 1.84 template struct random_number_generator<tausworthe_random_generator>;
86     template struct random_number_generator<xorshift_random_generator>;
87    
88 sf-marcmagus 1.87 /******************************************************************************/
89    
90     /* Checks a player-provided string which will become the msg property of
91     * an object for dangerous input.
92     */
93     bool
94     msg_is_safe (const char *msg)
95     {
96     bool safe = true;
97    
98     /* Trying to cheat by getting data into the object */
99 root 1.88 if (!strncmp (msg, "endmsg", sizeof ("endmsg") - 1)
100     || strstr (msg, "\nendmsg"))
101 sf-marcmagus 1.87 safe = false;
102    
103     /* Trying to make the object talk, and potentially access arbitrary code */
104     if (object::msg_has_dialogue (msg))
105     safe = false;
106    
107     return safe;
108     }
109    
110 root 1.14 /////////////////////////////////////////////////////////////////////////////
111    
112 root 1.37 void
113     fork_abort (const char *msg)
114     {
115     if (!fork ())
116     {
117 root 1.80 signal (SIGINT , SIG_IGN);
118     signal (SIGTERM, SIG_IGN);
119     signal (SIGABRT, SIG_IGN);
120 root 1.79
121 root 1.81 signal (SIGSEGV, SIG_DFL);
122     signal (SIGBUS , SIG_DFL);
123     signal (SIGILL , SIG_DFL);
124     signal (SIGTRAP, SIG_DFL);
125    
126 root 1.52 // try to put corefiles into a subdirectory, if existing, to allow
127     // an administrator to reduce the I/O load.
128     chdir ("cores");
129 root 1.79
130     // try to detach us from as many external dependencies as possible
131     // as coredumping can take time by closing all fd's.
132     {
133     struct rlimit lim;
134    
135     if (getrlimit (RLIMIT_NOFILE, &lim))
136     lim.rlim_cur = 1024;
137    
138     for (int i = 0; i < lim.rlim_cur; ++i)
139     close (i);
140     }
141    
142 root 1.81 {
143     sigset_t empty;
144     sigemptyset (&empty);
145     sigprocmask (SIG_SETMASK, &empty, 0);
146     }
147    
148     // try to coredump with SIGTRAP
149     kill (getpid (), SIGTRAP);
150 root 1.37 abort ();
151     }
152    
153 root 1.38 LOG (llevError, "fork abort: %s\n", msg);
154 root 1.37 }
155 root 1.38
156 root 1.25 void *salloc_ (int n) throw (std::bad_alloc)
157 root 1.10 {
158 root 1.25 void *ptr = g_slice_alloc (n);
159 root 1.13
160 root 1.23 if (!ptr)
161 root 1.13 throw std::bad_alloc ();
162 root 1.4
163 root 1.74 slice_alloc += n;
164 root 1.23 return ptr;
165     }
166    
167 root 1.25 void *salloc_ (int n, void *src) throw (std::bad_alloc)
168 root 1.23 {
169 root 1.25 void *ptr = salloc_ (n);
170 root 1.23
171 root 1.24 if (src)
172 root 1.25 memcpy (ptr, src, n);
173 root 1.24 else
174 root 1.25 memset (ptr, 0, n);
175 root 1.23
176     return ptr;
177 root 1.3 }
178 root 1.11
179 root 1.69 /******************************************************************************/
180    
181 root 1.72 #if DEBUG_SALLOC
182 root 1.69
183 root 1.70 #define MAGIC 0xa1b2c35543deadLL
184 root 1.69
185     void *g_slice_alloc (unsigned long size)
186     {
187     unsigned long *p = (unsigned long *) (g_slice_alloc)(size + sizeof (unsigned long));
188     *p++ = size ^ MAGIC;
189     //fprintf (stderr, "g_slice_alloc %ld %p\n", size, p);//D
190     return (void *)p;
191     }
192    
193     void *g_slice_alloc0 (unsigned long size)
194     {
195     return memset (g_slice_alloc (size), 0, size);
196     }
197    
198     void g_slice_free1 (unsigned long size, void *ptr)
199     {
200 root 1.74 //fprintf (stderr, "g_slice_free %ld %p\n", size, ptr);//D
201 root 1.69 if (expect_true (ptr))
202     {
203     unsigned long *p = (unsigned long *)ptr;
204     unsigned long s = *--p ^ MAGIC;
205    
206 root 1.71 if (size != (unsigned long)(*p ^ MAGIC))
207 root 1.74 {
208     LOG (logBacktrace | llevError, "slice free size (%lx) doesn't match alloc size (%lx)\n", size, s);
209     abort ();
210     }
211 root 1.69
212     *p = MAGIC;
213    
214     (g_slice_free1)(s + sizeof (unsigned long), p);
215     }
216     }
217    
218     #endif
219    
220     /******************************************************************************/
221    
222 root 1.86 int
223     assign (char *dst, const char *src, int maxsize)
224 root 1.11 {
225     if (!src)
226     src = "";
227    
228     int len = strlen (src);
229    
230 root 1.86 if (len >= maxsize)
231 root 1.11 {
232 root 1.86 if (maxsize <= 4)
233 root 1.11 {
234 root 1.86 memset (dst, '.', maxsize - 2);
235     dst [maxsize - 1] = 0;
236 root 1.11 }
237     else
238     {
239 root 1.86 memcpy (dst, src, maxsize - 4);
240     memcpy (dst + maxsize - 4, "...", 4);
241 root 1.11 }
242 root 1.86
243     len = maxsize;
244 root 1.11 }
245     else
246 root 1.86 memcpy (dst, src, ++len);
247    
248     return len;
249 root 1.11 }
250    
251 root 1.90 char *
252     vformat (const char *format, va_list ap)
253     {
254     static dynbuf_text buf; buf.clear ();
255     buf.vprintf (format, ap);
256     return buf;
257     }
258    
259     char *
260 root 1.51 format (const char *format, ...)
261     {
262 root 1.65 va_list ap;
263     va_start (ap, format);
264 root 1.90 char *buf = vformat (format, ap);
265 root 1.65 va_end (ap);
266    
267     return buf;
268 root 1.51 }
269    
270 root 1.23 tstamp now ()
271     {
272     struct timeval tv;
273    
274     gettimeofday (&tv, 0);
275     return tstamp (tv.tv_sec) + tstamp (tv.tv_usec) * tstamp (1e-6);
276     }
277 root 1.17
278 root 1.32 int
279     similar_direction (int a, int b)
280     {
281     if (!a || !b)
282     return 0;
283    
284     int diff = (b - a) & 7;
285     return diff <= 1 || diff >= 7;
286     }
287    
288 root 1.48 /* crc32 0xdebb20e3 table and supplementary functions. */
289     extern const uint32_t crc_32_tab[256] =
290     {
291     0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
292     0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
293     0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
294     0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
295     0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
296     0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
297     0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
298     0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
299     0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
300     0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
301     0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
302     0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
303     0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
304     0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
305     0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
306     0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
307     0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
308     0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
309     0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
310     0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
311     0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
312     0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
313     0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
314     0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
315     0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
316     0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
317     0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
318     0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
319     0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
320     0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
321     0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
322     0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
323     0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
324     0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
325     0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
326     0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
327     0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
328     0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
329     0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
330     0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
331     0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
332     0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
333     0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
334     0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
335     0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
336     0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
337     0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
338     0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
339     0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
340     0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
341     0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
342     0x2d02ef8dL
343     };
344    
345 root 1.73 void thread::start (void *(*start_routine)(void *), void *arg)
346     {
347 root 1.75 pthread_attr_t attr;
348    
349     pthread_attr_init (&attr);
350     pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
351     pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN < sizeof (long) * 4096
352     ? sizeof (long) * 4096 : PTHREAD_STACK_MIN);
353     #ifdef PTHREAD_SCOPE_PROCESS
354     pthread_attr_setscope (&attr, PTHREAD_SCOPE_PROCESS);
355     #endif
356    
357 root 1.73 sigset_t fullsigset, oldsigset;
358     sigfillset (&fullsigset);
359    
360     pthread_sigmask (SIG_SETMASK, &fullsigset, &oldsigset);
361    
362 root 1.75 if (pthread_create (&id, &attr, start_routine, arg))
363 root 1.73 cleanup ("unable to create a new thread");
364    
365     pthread_sigmask (SIG_SETMASK, &oldsigset, 0);
366     }
367 root 1.75