ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/utils.C
Revision: 1.104
Committed: Wed Nov 16 23:41:59 2016 UTC (7 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.103: +1 -1 lines
Log Message:
copyright update 2016

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