ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/utils.C
Revision: 1.88
Committed: Sun Oct 11 05:31:54 2009 UTC (14 years, 7 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.87: +2 -1 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 pippijn 1.39 *
4 root 1.74 * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 root 1.57 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
6     * Copyright (©) 1992,2007 Frank Tore Johansen
7 pippijn 1.39 *
8 root 1.68 * Deliantra is free software: you can redistribute it and/or modify
9 root 1.60 * it under the terms of the GNU General Public License as published by
10     * the Free Software Foundation, either version 3 of the License, or
11     * (at your option) any later version.
12 pippijn 1.39 *
13 root 1.60 * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17 pippijn 1.39 *
18 root 1.60 * You should have received a copy of the GNU General Public License
19     * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 root 1.57 *
21 root 1.68 * The authors can be reached via e-mail to <support@deliantra.net>
22 pippijn 1.39 */
23 elmex 1.1
24     /*
25     * General convenience functions for crossfire.
26     */
27    
28 root 1.37 #include <cstdlib>
29     #include <sys/types.h>
30     #include <unistd.h>
31     #include <sys/time.h>
32     #include <time.h>
33     #include <signal.h>
34    
35 elmex 1.1 #include <global.h>
36     #include <material.h>
37 sf-marcmagus 1.87 #include <object.h>
38 elmex 1.1
39 root 1.79 #include <sys/time.h>
40     #include <sys/resource.h>
41    
42 root 1.4 #include <glib.h>
43    
44 root 1.63 refcnt_base::refcnt_t refcnt_dummy;
45 root 1.74 ssize_t slice_alloc;
46 root 1.77 rand_gen rndm, rmg_rndm;
47 root 1.40
48 root 1.42 void
49     tausworthe_random_generator::seed (uint32_t seed)
50 root 1.40 {
51 root 1.74 state [0] = seed * 69069U; if (state [0] < 2U) state [0] += 2U;
52     state [1] = state [0] * 69069U; if (state [0] < 8U) state [0] += 8U;
53     state [2] = state [1] * 69069U; if (state [0] < 16U) state [0] += 16U;
54     state [3] = state [2] * 69069U; if (state [0] < 128U) state [0] += 128U;
55 root 1.40
56     for (int i = 11; --i; )
57 root 1.84 next ();
58 root 1.40 }
59    
60     uint32_t
61     tausworthe_random_generator::next ()
62     {
63     state [0] = ((state [0] & 0xFFFFFFFEU) << 18U) ^ (((state [0] << 6U) ^ state [0]) >> 13U);
64     state [1] = ((state [1] & 0xFFFFFFF8U) << 2U) ^ (((state [1] << 2U) ^ state [1]) >> 27U);
65     state [2] = ((state [2] & 0xFFFFFFF0U) << 7U) ^ (((state [2] << 13U) ^ state [2]) >> 21U);
66     state [3] = ((state [3] & 0xFFFFFF80U) << 13U) ^ (((state [3] << 3U) ^ state [3]) >> 12U);
67    
68     return state [0] ^ state [1] ^ state [2] ^ state [3];
69     }
70    
71 root 1.84 template<class generator>
72 root 1.42 uint32_t
73 root 1.84 random_number_generator<generator>::get_range (uint32_t num)
74 root 1.42 {
75 root 1.84 return (this->next () * (uint64_t)num) >> 32U;
76 root 1.42 }
77    
78     // return a number within (min .. max)
79 root 1.84 template<class generator>
80 root 1.42 int
81 root 1.84 random_number_generator<generator>::get_range (int r_min, int r_max)
82 root 1.42 {
83 root 1.50 return r_min + get_range (max (r_max - r_min + 1, 0));
84 root 1.42 }
85    
86 root 1.84 template struct random_number_generator<tausworthe_random_generator>;
87     template struct random_number_generator<xorshift_random_generator>;
88    
89 elmex 1.1 /*
90     * The random functions here take luck into account when rolling random
91     * dice or numbers. This function has less of an impact the larger the
92     * difference becomes in the random numbers. IE, the effect is lessened
93     * on a 1-1000 roll, vs a 1-6 roll. This can be used by crafty programmers,
94     * to specifically disable luck in certain rolls, simply by making the
95     * numbers larger (ie, 1d1000 > 500 vs 1d6 > 3)
96     */
97    
98     /*
99     * Roll a random number between min and max. Uses op to determine luck,
100     * and if goodbad is non-zero, luck increases the roll, if zero, it decreases.
101     * Generally, op should be the player/caster/hitter requesting the roll,
102     * not the recipient (ie, the poor slob getting hit). [garbled 20010916]
103     */
104 root 1.9 int
105 root 1.41 random_roll (int r_min, int r_max, const object *op, int goodbad)
106 root 1.9 {
107 root 1.78 r_max = max (r_min, r_max);
108    
109 root 1.41 int base = r_max - r_min > 1 ? 20 : 50; /* d2 and d3 are corner cases */
110 elmex 1.1
111 root 1.41 if (op->type == PLAYER)
112 root 1.9 {
113 root 1.41 int luck = op->stats.luck;
114 elmex 1.1
115 root 1.41 if (rndm (base) < min (10, abs (luck)))
116     {
117     //TODO: take luck into account
118     }
119 elmex 1.1 }
120 root 1.41
121     return rndm (r_min, r_max);
122 elmex 1.1 }
123    
124     /*
125     * This is a 64 bit version of random_roll above. This is needed
126     * for exp loss calculations for players changing religions.
127     */
128 root 1.9 sint64
129 root 1.78 random_roll64 (sint64 r_min, sint64 r_max, const object *op, int goodbad)
130 root 1.9 {
131 root 1.78 sint64 omin = r_min;
132     sint64 range = max (0, r_max - r_min + 1);
133     int base = range > 2 ? 20 : 50; /* d2 and d3 are corner cases */
134 elmex 1.1
135 root 1.45 /*
136     * Make a call to get two 32 bit unsigned random numbers, and just to
137     * a little bitshifting.
138 root 1.9 */
139 root 1.55 sint64 ran = (sint64) rndm.next () ^ ((sint64) rndm.next () << 31);
140 root 1.9
141     if (op->type != PLAYER)
142 root 1.78 return ((ran % range) + r_min);
143 root 1.9
144 root 1.55 int luck = op->stats.luck;
145    
146 root 1.78 if (rndm (base) < min (10, abs (luck)))
147 root 1.9 {
148     /* we have a winner */
149     ((luck > 0) ? (luck = 1) : (luck = -1));
150 root 1.78 range -= luck;
151     if (range < 1)
152 root 1.9 return (omin); /*check again */
153 root 1.55
154 root 1.78 ((goodbad) ? (r_min += luck) : (range));
155 elmex 1.1
156 root 1.78 return (max (omin, min (r_max, (ran % range) + r_min)));
157 elmex 1.1 }
158 root 1.45
159 root 1.78 return ran % range + r_min;
160 elmex 1.1 }
161    
162     /*
163     * Roll a number of dice (2d3, 4d6). Uses op to determine luck,
164     * If goodbad is non-zero, luck increases the roll, if zero, it decreases.
165     * Generally, op should be the player/caster/hitter requesting the roll,
166     * not the recipient (ie, the poor slob getting hit).
167     * The args are num D size (ie 4d6) [garbled 20010916]
168     */
169 root 1.9 int
170     die_roll (int num, int size, const object *op, int goodbad)
171     {
172 root 1.55 int min, luck, total, i, gotlucky;
173 root 1.9
174 root 1.55 int diff = size;
175 root 1.9 min = 1;
176     luck = total = gotlucky = 0;
177 root 1.55 int base = diff > 2 ? 20 : 50; /* d2 and d3 are corner cases */
178    
179 root 1.9 if (size < 2 || diff < 1)
180     {
181     LOG (llevError, "Calling die_roll with num=%d size=%d\n", num, size);
182 root 1.55 return num; /* avoids a float exception */
183 root 1.9 }
184 elmex 1.1
185 root 1.9 if (op->type == PLAYER)
186     luck = op->stats.luck;
187    
188     for (i = 0; i < num; i++)
189     {
190 root 1.45 if (rndm (base) < MIN (10, abs (luck)) && !gotlucky)
191 root 1.9 {
192     /* we have a winner */
193     gotlucky++;
194     ((luck > 0) ? (luck = 1) : (luck = -1));
195     diff -= luck;
196     if (diff < 1)
197     return (num); /*check again */
198     ((goodbad) ? (min += luck) : (diff));
199 root 1.45 total += MAX (1, MIN (size, rndm (diff) + min));
200 root 1.9 }
201     else
202 root 1.45 total += rndm (size) + 1;
203 elmex 1.1 }
204 root 1.45
205     return total;
206 elmex 1.1 }
207    
208     /* convert materialname to materialtype_t */
209    
210 root 1.9 materialtype_t *
211 root 1.83 name_to_material (const shstr_cmp name)
212 elmex 1.1 {
213 root 1.83 for (materialtype_t *mt = materialt; mt; mt = mt->next)
214 root 1.47 if (name == mt->name)
215     return mt;
216 elmex 1.1
217 root 1.62 return 0;
218 elmex 1.1 }
219    
220     /* when doing transmutation of objects, we have to recheck the resistances,
221     * as some that did not apply previously, may apply now.
222     */
223 root 1.9 void
224     transmute_materialname (object *op, const object *change)
225 elmex 1.1 {
226 root 1.9 materialtype_t *mt;
227     int j;
228 elmex 1.1
229 root 1.83 if (!op->materialname)
230 root 1.9 return;
231 elmex 1.1
232 root 1.85 if (op->materialname != change->materialname)
233 root 1.9 return;
234    
235 root 1.26 if (!op->is_armor ())
236 root 1.9 return;
237    
238     mt = name_to_material (op->materialname);
239     if (!mt)
240     {
241 root 1.58 LOG (llevError, "archetype '%s>%s' uses nonexistent material '%s'\n", &op->arch->archname, &op->name, &op->materialname);
242 root 1.9 return;
243     }
244    
245     for (j = 0; j < NROFATTACKS; j++)
246     if (op->resist[j] == 0 && change->resist[j] != 0)
247     {
248     op->resist[j] += mt->mod[j];
249     if (op->resist[j] > 100)
250     op->resist[j] = 100;
251     if (op->resist[j] < -100)
252     op->resist[j] = -100;
253     }
254 elmex 1.1 }
255    
256     /* set the materialname and type for an item */
257 root 1.9 void
258     set_materialname (object *op, int difficulty, materialtype_t *nmt)
259 elmex 1.1 {
260 root 1.9 materialtype_t *mt, *lmt;
261    
262 root 1.83 if (!op->materialname)
263 root 1.9 return;
264 elmex 1.1
265 root 1.83 if (nmt)
266     lmt = nmt;
267     else
268 root 1.9 {
269 root 1.83 lmt = 0;
270 root 1.61
271 root 1.83 for (mt = materialt; mt; mt = mt->next)
272 root 1.61 if (op->materials & mt->material && rndm (1, 100) <= mt->chance &&
273     difficulty >= mt->difficulty && (op->magic >= mt->magic || mt->magic == 0))
274     {
275     lmt = mt;
276     if (!(op->is_weapon () || op->is_armor ()))
277 root 1.9 break;
278 root 1.61 }
279 root 1.9 }
280 elmex 1.1
281 root 1.83 if (lmt)
282 root 1.9 {
283 root 1.26 if (op->stats.dam && op->is_weapon ())
284 root 1.9 {
285     op->stats.dam += lmt->damage;
286     if (op->stats.dam < 1)
287     op->stats.dam = 1;
288     }
289 root 1.46
290 root 1.9 if (op->stats.sp && op->type == BOW)
291     op->stats.sp += lmt->sp;
292 root 1.26 if (op->stats.wc && op->is_weapon ())
293 root 1.9 op->stats.wc += lmt->wc;
294 root 1.26 if (op->is_armor ())
295 root 1.9 {
296     if (op->stats.ac)
297     op->stats.ac += lmt->ac;
298 root 1.61
299     for (int j = 0; j < NROFATTACKS; j++)
300 root 1.9 if (op->resist[j] != 0)
301     {
302     op->resist[j] += lmt->mod[j];
303     if (op->resist[j] > 100)
304     op->resist[j] = 100;
305     if (op->resist[j] < -100)
306     op->resist[j] = -100;
307     }
308     }
309 root 1.61
310 root 1.46 op->materialname = lmt->name;
311 root 1.9 /* dont make it unstackable if it doesn't need to be */
312 root 1.26 if (op->is_weapon () || op->is_armor ())
313 root 1.9 {
314     op->weight = (op->weight * lmt->weight) / 100;
315     op->value = (op->value * lmt->value) / 100;
316 root 1.2 }
317 elmex 1.1 }
318     }
319    
320     /*
321     * Strip out the media tags from a String.
322     * Warning the input string will contain the result string
323     */
324 root 1.9 void
325     strip_media_tag (char *message)
326     {
327     int in_tag = 0;
328     char *dest;
329     char *src;
330    
331     src = dest = message;
332     while (*src != '\0')
333     {
334     if (*src == '[')
335     {
336     in_tag = 1;
337     }
338     else if (in_tag && (*src == ']'))
339     in_tag = 0;
340     else if (!in_tag)
341     {
342     *dest = *src;
343     dest++;
344     }
345     src++;
346     }
347     *dest = '\0';
348     }
349    
350     const char *
351     strrstr (const char *haystack, const char *needle)
352     {
353     const char *lastneedle;
354    
355     lastneedle = NULL;
356     while ((haystack = strstr (haystack, needle)) != NULL)
357     {
358     lastneedle = haystack;
359     haystack++;
360 elmex 1.1 }
361 root 1.9 return lastneedle;
362    
363 elmex 1.1 }
364 root 1.9
365 elmex 1.1 #define EOL_SIZE (sizeof("\n")-1)
366 root 1.9 void
367     strip_endline (char *buf)
368     {
369     if (strlen (buf) < sizeof ("\n"))
370     {
371     return;
372 elmex 1.1 }
373 root 1.9 if (!strcmp (buf + strlen (buf) - EOL_SIZE, "\n"))
374     buf[strlen (buf) - EOL_SIZE] = '\0';
375 elmex 1.1 }
376    
377     /**
378     * Replace in string src all occurrences of key by replacement. The resulting
379     * string is put into result; at most resultsize characters (including the
380     * terminating null character) will be written to result.
381     */
382 root 1.9 void
383     replace (const char *src, const char *key, const char *replacement, char *result, size_t resultsize)
384 elmex 1.1 {
385 root 1.9 size_t resultlen;
386     size_t keylen;
387 elmex 1.1
388 root 1.9 /* special case to prevent infinite loop if key==replacement=="" */
389     if (strcmp (key, replacement) == 0)
390     {
391     snprintf (result, resultsize, "%s", src);
392     return;
393     }
394    
395     keylen = strlen (key);
396    
397     resultlen = 0;
398     while (*src != '\0' && resultlen + 1 < resultsize)
399     {
400     if (strncmp (src, key, keylen) == 0)
401 root 1.2 {
402 root 1.9 snprintf (result + resultlen, resultsize - resultlen, "%s", replacement);
403     resultlen += strlen (result + resultlen);
404     src += keylen;
405 root 1.2 }
406 root 1.9 else
407 root 1.2 {
408 root 1.9 result[resultlen++] = *src++;
409 root 1.2 }
410 root 1.9 }
411     result[resultlen] = '\0';
412 elmex 1.1 }
413    
414     /**
415     * Taking a string as an argument, mutate it into a string that looks like a list.
416     * a 'list' for the purposes here, is a string of items, seperated by commas, except
417     * for the last entry, which has an 'and' before it, and a full stop (period) after it.
418     * This function will also strip all trailing non alphanumeric characters.
419     * It does not insert an oxford comma.
420     */
421 root 1.9 void
422     make_list_like (char *input)
423     {
424     char *p, tmp[MAX_BUF];
425     int i;
426    
427     if (!input || strlen (input) > MAX_BUF - 5)
428 elmex 1.1 return;
429 root 1.9 /* bad stuff would happen if we continued here, the -5 is to make space for ' and ' */
430    
431     strncpy (tmp, input, MAX_BUF - 5);
432     /*trim all trailing commas, spaces etc. */
433     for (i = strlen (tmp); !isalnum (tmp[i]) && i >= 0; i--)
434     tmp[i] = '\0';
435 root 1.11
436 root 1.9 strcat (tmp, ".");
437    
438     p = strrchr (tmp, ',');
439     if (p)
440     {
441     *p = '\0';
442     strcpy (input, tmp);
443     p++;
444     strcat (input, " and");
445     strcat (input, p);
446     }
447     else
448     strcpy (input, tmp);
449 root 1.11
450 root 1.9 return;
451 elmex 1.1 }
452 root 1.3
453 sf-marcmagus 1.87 /******************************************************************************/
454    
455     /* Checks a player-provided string which will become the msg property of
456     * an object for dangerous input.
457     */
458     bool
459     msg_is_safe (const char *msg)
460     {
461     bool safe = true;
462    
463     /* Trying to cheat by getting data into the object */
464 root 1.88 if (!strncmp (msg, "endmsg", sizeof ("endmsg") - 1)
465     || strstr (msg, "\nendmsg"))
466 sf-marcmagus 1.87 safe = false;
467    
468     /* Trying to make the object talk, and potentially access arbitrary code */
469     if (object::msg_has_dialogue (msg))
470     safe = false;
471    
472     return safe;
473     }
474    
475 root 1.14 /////////////////////////////////////////////////////////////////////////////
476    
477 root 1.37 void
478     fork_abort (const char *msg)
479     {
480     if (!fork ())
481     {
482 root 1.80 signal (SIGINT , SIG_IGN);
483     signal (SIGTERM, SIG_IGN);
484     signal (SIGABRT, SIG_IGN);
485 root 1.79
486 root 1.81 signal (SIGSEGV, SIG_DFL);
487     signal (SIGBUS , SIG_DFL);
488     signal (SIGILL , SIG_DFL);
489     signal (SIGTRAP, SIG_DFL);
490    
491 root 1.52 // try to put corefiles into a subdirectory, if existing, to allow
492     // an administrator to reduce the I/O load.
493     chdir ("cores");
494 root 1.79
495     // try to detach us from as many external dependencies as possible
496     // as coredumping can take time by closing all fd's.
497     {
498     struct rlimit lim;
499    
500     if (getrlimit (RLIMIT_NOFILE, &lim))
501     lim.rlim_cur = 1024;
502    
503     for (int i = 0; i < lim.rlim_cur; ++i)
504     close (i);
505     }
506    
507 root 1.81 {
508     sigset_t empty;
509     sigemptyset (&empty);
510     sigprocmask (SIG_SETMASK, &empty, 0);
511     }
512    
513     // try to coredump with SIGTRAP
514     kill (getpid (), SIGTRAP);
515 root 1.37 abort ();
516     }
517    
518 root 1.38 LOG (llevError, "fork abort: %s\n", msg);
519 root 1.37 }
520 root 1.38
521 root 1.25 void *salloc_ (int n) throw (std::bad_alloc)
522 root 1.10 {
523 root 1.25 void *ptr = g_slice_alloc (n);
524 root 1.13
525 root 1.23 if (!ptr)
526 root 1.13 throw std::bad_alloc ();
527 root 1.4
528 root 1.74 slice_alloc += n;
529 root 1.23 return ptr;
530     }
531    
532 root 1.25 void *salloc_ (int n, void *src) throw (std::bad_alloc)
533 root 1.23 {
534 root 1.25 void *ptr = salloc_ (n);
535 root 1.23
536 root 1.24 if (src)
537 root 1.25 memcpy (ptr, src, n);
538 root 1.24 else
539 root 1.25 memset (ptr, 0, n);
540 root 1.23
541     return ptr;
542 root 1.3 }
543 root 1.11
544 root 1.69 /******************************************************************************/
545    
546 root 1.72 #if DEBUG_SALLOC
547 root 1.69
548 root 1.70 #define MAGIC 0xa1b2c35543deadLL
549 root 1.69
550     void *g_slice_alloc (unsigned long size)
551     {
552     unsigned long *p = (unsigned long *) (g_slice_alloc)(size + sizeof (unsigned long));
553     *p++ = size ^ MAGIC;
554     //fprintf (stderr, "g_slice_alloc %ld %p\n", size, p);//D
555     return (void *)p;
556     }
557    
558     void *g_slice_alloc0 (unsigned long size)
559     {
560     return memset (g_slice_alloc (size), 0, size);
561     }
562    
563     void g_slice_free1 (unsigned long size, void *ptr)
564     {
565 root 1.74 //fprintf (stderr, "g_slice_free %ld %p\n", size, ptr);//D
566 root 1.69 if (expect_true (ptr))
567     {
568     unsigned long *p = (unsigned long *)ptr;
569     unsigned long s = *--p ^ MAGIC;
570    
571 root 1.71 if (size != (unsigned long)(*p ^ MAGIC))
572 root 1.74 {
573     LOG (logBacktrace | llevError, "slice free size (%lx) doesn't match alloc size (%lx)\n", size, s);
574     abort ();
575     }
576 root 1.69
577     *p = MAGIC;
578    
579     (g_slice_free1)(s + sizeof (unsigned long), p);
580     }
581     }
582    
583     #endif
584    
585     /******************************************************************************/
586    
587 root 1.86 int
588     assign (char *dst, const char *src, int maxsize)
589 root 1.11 {
590     if (!src)
591     src = "";
592    
593     int len = strlen (src);
594    
595 root 1.86 if (len >= maxsize)
596 root 1.11 {
597 root 1.86 if (maxsize <= 4)
598 root 1.11 {
599 root 1.86 memset (dst, '.', maxsize - 2);
600     dst [maxsize - 1] = 0;
601 root 1.11 }
602     else
603     {
604 root 1.86 memcpy (dst, src, maxsize - 4);
605     memcpy (dst + maxsize - 4, "...", 4);
606 root 1.11 }
607 root 1.86
608     len = maxsize;
609 root 1.11 }
610     else
611 root 1.86 memcpy (dst, src, ++len);
612    
613     return len;
614 root 1.11 }
615    
616 root 1.65 const char *
617 root 1.51 format (const char *format, ...)
618     {
619 root 1.65 static dynbuf_text buf;
620 root 1.51
621 root 1.65 buf.clear ();
622 root 1.51
623 root 1.65 va_list ap;
624     va_start (ap, format);
625     buf.vprintf (format, ap);
626     va_end (ap);
627    
628     return buf;
629 root 1.51 }
630    
631 root 1.23 tstamp now ()
632     {
633     struct timeval tv;
634    
635     gettimeofday (&tv, 0);
636     return tstamp (tv.tv_sec) + tstamp (tv.tv_usec) * tstamp (1e-6);
637     }
638 root 1.17
639 root 1.32 int
640     similar_direction (int a, int b)
641     {
642     if (!a || !b)
643     return 0;
644    
645     int diff = (b - a) & 7;
646     return diff <= 1 || diff >= 7;
647     }
648    
649 root 1.48 /* crc32 0xdebb20e3 table and supplementary functions. */
650     extern const uint32_t crc_32_tab[256] =
651     {
652     0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
653     0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
654     0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
655     0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
656     0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
657     0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
658     0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
659     0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
660     0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
661     0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
662     0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
663     0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
664     0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
665     0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
666     0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
667     0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
668     0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
669     0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
670     0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
671     0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
672     0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
673     0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
674     0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
675     0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
676     0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
677     0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
678     0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
679     0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
680     0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
681     0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
682     0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
683     0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
684     0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
685     0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
686     0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
687     0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
688     0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
689     0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
690     0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
691     0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
692     0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
693     0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
694     0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
695     0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
696     0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
697     0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
698     0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
699     0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
700     0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
701     0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
702     0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
703     0x2d02ef8dL
704     };
705    
706 root 1.73 void thread::start (void *(*start_routine)(void *), void *arg)
707     {
708 root 1.75 pthread_attr_t attr;
709    
710     pthread_attr_init (&attr);
711     pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
712     pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN < sizeof (long) * 4096
713     ? sizeof (long) * 4096 : PTHREAD_STACK_MIN);
714     #ifdef PTHREAD_SCOPE_PROCESS
715     pthread_attr_setscope (&attr, PTHREAD_SCOPE_PROCESS);
716     #endif
717    
718 root 1.73 sigset_t fullsigset, oldsigset;
719     sigfillset (&fullsigset);
720    
721     pthread_sigmask (SIG_SETMASK, &fullsigset, &oldsigset);
722    
723 root 1.75 if (pthread_create (&id, &attr, start_routine, arg))
724 root 1.73 cleanup ("unable to create a new thread");
725    
726     pthread_sigmask (SIG_SETMASK, &oldsigset, 0);
727     }
728 root 1.75