ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/deliantra/server/common/utils.C
Revision: 1.102
Committed: Sun Nov 11 01:27:44 2012 UTC (13 years, 11 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.101: +11 -2 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 elmex 1.1 /*
2 root 1.68 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 root 1.101 *
4 root 1.100 * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 root 1.101 *
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 root 1.101 *
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 root 1.101 *
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.101 *
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.40
46 root 1.94 #if !GCC_VERSION(3,4)
47     int least_significant_bit (uint32_t x)
48     {
49     x &= -x; // this isolates the lowest bit
50    
51     int r = 0;
52    
53     if (x & 0xaaaaaaaa) r += 1;
54     if (x & 0xcccccccc) r += 2;
55     if (x & 0xf0f0f0f0) r += 4;
56     if (x & 0xff00ff00) r += 8;
57     if (x & 0xffff0000) r += 16;
58    
59     return r;
60     }
61     #endif
62    
63 sf-marcmagus 1.87 /******************************************************************************/
64    
65     /* Checks a player-provided string which will become the msg property of
66     * an object for dangerous input.
67     */
68     bool
69     msg_is_safe (const char *msg)
70     {
71     bool safe = true;
72    
73     /* Trying to cheat by getting data into the object */
74 root 1.88 if (!strncmp (msg, "endmsg", sizeof ("endmsg") - 1)
75     || strstr (msg, "\nendmsg"))
76 sf-marcmagus 1.87 safe = false;
77    
78     /* Trying to make the object talk, and potentially access arbitrary code */
79     if (object::msg_has_dialogue (msg))
80     safe = false;
81    
82     return safe;
83     }
84    
85 root 1.14 /////////////////////////////////////////////////////////////////////////////
86    
87 root 1.37 void
88     fork_abort (const char *msg)
89     {
90     if (!fork ())
91     {
92 root 1.80 signal (SIGINT , SIG_IGN);
93     signal (SIGTERM, SIG_IGN);
94     signal (SIGABRT, SIG_IGN);
95 root 1.79
96 root 1.81 signal (SIGSEGV, SIG_DFL);
97     signal (SIGBUS , SIG_DFL);
98     signal (SIGILL , SIG_DFL);
99     signal (SIGTRAP, SIG_DFL);
100    
101 root 1.52 // try to put corefiles into a subdirectory, if existing, to allow
102     // an administrator to reduce the I/O load.
103     chdir ("cores");
104 root 1.79
105     // try to detach us from as many external dependencies as possible
106     // as coredumping can take time by closing all fd's.
107     {
108     struct rlimit lim;
109    
110     if (getrlimit (RLIMIT_NOFILE, &lim))
111     lim.rlim_cur = 1024;
112    
113     for (int i = 0; i < lim.rlim_cur; ++i)
114     close (i);
115     }
116    
117 root 1.81 {
118     sigset_t empty;
119     sigemptyset (&empty);
120     sigprocmask (SIG_SETMASK, &empty, 0);
121     }
122    
123     // try to coredump with SIGTRAP
124     kill (getpid (), SIGTRAP);
125 root 1.37 abort ();
126     }
127    
128 root 1.38 LOG (llevError, "fork abort: %s\n", msg);
129 root 1.37 }
130 root 1.38
131 root 1.99 void *
132     salloc_ (int n) throw (std::bad_alloc)
133 root 1.10 {
134 root 1.25 void *ptr = g_slice_alloc (n);
135 root 1.13
136 root 1.23 if (!ptr)
137 root 1.13 throw std::bad_alloc ();
138 root 1.4
139 root 1.74 slice_alloc += n;
140 root 1.23 return ptr;
141     }
142    
143 root 1.99 void *
144     salloc_ (int n, void *src) throw (std::bad_alloc)
145 root 1.23 {
146 root 1.25 void *ptr = salloc_ (n);
147 root 1.23
148 root 1.24 if (src)
149 root 1.25 memcpy (ptr, src, n);
150 root 1.24 else
151 root 1.25 memset (ptr, 0, n);
152 root 1.23
153     return ptr;
154 root 1.3 }
155 root 1.11
156 root 1.69 /******************************************************************************/
157    
158 root 1.72 #if DEBUG_SALLOC
159 root 1.69
160 root 1.70 #define MAGIC 0xa1b2c35543deadLL
161 root 1.69
162 root 1.99 void *
163     g_slice_alloc (unsigned long size)
164 root 1.69 {
165     unsigned long *p = (unsigned long *) (g_slice_alloc)(size + sizeof (unsigned long));
166     *p++ = size ^ MAGIC;
167     //fprintf (stderr, "g_slice_alloc %ld %p\n", size, p);//D
168     return (void *)p;
169     }
170    
171 root 1.99 void *
172     g_slice_alloc0 (unsigned long size)
173 root 1.69 {
174     return memset (g_slice_alloc (size), 0, size);
175     }
176    
177 root 1.99 void
178     g_slice_free1 (unsigned long size, void *ptr)
179 root 1.69 {
180 root 1.74 //fprintf (stderr, "g_slice_free %ld %p\n", size, ptr);//D
181 root 1.69 if (expect_true (ptr))
182     {
183     unsigned long *p = (unsigned long *)ptr;
184     unsigned long s = *--p ^ MAGIC;
185    
186 root 1.71 if (size != (unsigned long)(*p ^ MAGIC))
187 root 1.74 {
188     LOG (logBacktrace | llevError, "slice free size (%lx) doesn't match alloc size (%lx)\n", size, s);
189     abort ();
190     }
191 root 1.69
192     *p = MAGIC;
193    
194     (g_slice_free1)(s + sizeof (unsigned long), p);
195     }
196     }
197    
198     #endif
199    
200     /******************************************************************************/
201    
202 root 1.99 refcnt_buf::refcnt_buf (size_t size)
203     {
204 root 1.102 static uint32_t empty_buf [2] = { 0, 1 }; // 2 == never deallocated
205     data = (char *)empty_buf + overhead;
206     assert (overhead == sizeof (empty_buf));
207     inc ();
208 root 1.99 }
209    
210     refcnt_buf::refcnt_buf (void *data, size_t size)
211     {
212     _alloc (size);
213     memcpy (this->data, data, size);
214     }
215    
216     refcnt_buf::~refcnt_buf ()
217     {
218     dec ();
219     }
220    
221 root 1.102 void
222     refcnt_buf::_dealloc ()
223     {
224     sfree<char> (data - overhead, size () + overhead);
225     }
226    
227 root 1.99 refcnt_buf &
228     refcnt_buf::operator =(const refcnt_buf &src)
229     {
230     dec ();
231     data = src.data;
232 root 1.102 inc ();
233 root 1.99 return *this;
234     }
235    
236     /******************************************************************************/
237    
238 root 1.86 int
239     assign (char *dst, const char *src, int maxsize)
240 root 1.11 {
241     if (!src)
242     src = "";
243    
244     int len = strlen (src);
245    
246 root 1.86 if (len >= maxsize)
247 root 1.11 {
248 root 1.86 if (maxsize <= 4)
249 root 1.11 {
250 root 1.86 memset (dst, '.', maxsize - 2);
251     dst [maxsize - 1] = 0;
252 root 1.11 }
253     else
254     {
255 root 1.86 memcpy (dst, src, maxsize - 4);
256     memcpy (dst + maxsize - 4, "...", 4);
257 root 1.11 }
258 root 1.86
259     len = maxsize;
260 root 1.11 }
261     else
262 root 1.86 memcpy (dst, src, ++len);
263    
264     return len;
265 root 1.11 }
266    
267 root 1.90 char *
268     vformat (const char *format, va_list ap)
269     {
270 root 1.96 static dynbuf_text bufs[8];
271     static int bufidx;
272    
273     dynbuf_text &buf = bufs [++bufidx & 7];
274    
275     buf.clear ();
276 root 1.90 buf.vprintf (format, ap);
277     return buf;
278     }
279    
280     char *
281 root 1.51 format (const char *format, ...)
282     {
283 root 1.65 va_list ap;
284     va_start (ap, format);
285 root 1.90 char *buf = vformat (format, ap);
286 root 1.65 va_end (ap);
287    
288     return buf;
289 root 1.51 }
290    
291 root 1.99 tstamp
292     now ()
293 root 1.23 {
294     struct timeval tv;
295    
296     gettimeofday (&tv, 0);
297     return tstamp (tv.tv_sec) + tstamp (tv.tv_usec) * tstamp (1e-6);
298     }
299 root 1.17
300 root 1.32 int
301     similar_direction (int a, int b)
302     {
303     if (!a || !b)
304     return 0;
305    
306     int diff = (b - a) & 7;
307     return diff <= 1 || diff >= 7;
308     }
309    
310 root 1.48 /* crc32 0xdebb20e3 table and supplementary functions. */
311     extern const uint32_t crc_32_tab[256] =
312     {
313     0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
314     0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
315     0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
316     0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
317     0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
318     0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
319     0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
320     0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
321     0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
322     0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
323     0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
324     0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
325     0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
326     0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
327     0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
328     0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
329     0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
330     0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
331     0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
332     0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
333     0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
334     0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
335     0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
336     0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
337     0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
338     0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
339     0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
340     0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
341     0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
342     0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
343     0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
344     0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
345     0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
346     0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
347     0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
348     0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
349     0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
350     0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
351     0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
352     0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
353     0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
354     0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
355     0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
356     0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
357     0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
358     0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
359     0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
360     0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
361     0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
362     0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
363     0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
364     0x2d02ef8dL
365     };
366    
367 root 1.99 void
368     thread::start (void *(*start_routine)(void *), void *arg)
369 root 1.73 {
370 root 1.75 pthread_attr_t attr;
371    
372     pthread_attr_init (&attr);
373     pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
374     pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN < sizeof (long) * 4096
375     ? sizeof (long) * 4096 : PTHREAD_STACK_MIN);
376     #ifdef PTHREAD_SCOPE_PROCESS
377     pthread_attr_setscope (&attr, PTHREAD_SCOPE_PROCESS);
378     #endif
379    
380 root 1.73 sigset_t fullsigset, oldsigset;
381     sigfillset (&fullsigset);
382    
383     pthread_sigmask (SIG_SETMASK, &fullsigset, &oldsigset);
384    
385 root 1.75 if (pthread_create (&id, &attr, start_routine, arg))
386 root 1.73 cleanup ("unable to create a new thread");
387    
388     pthread_sigmask (SIG_SETMASK, &oldsigset, 0);
389     }
390 root 1.75