ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/utils.C
(Generate patch)

Comparing deliantra/server/common/utils.C (file contents):
Revision 1.69 by root, Tue Jan 22 15:53:01 2008 UTC vs.
Revision 1.90 by root, Thu Oct 15 21:09:32 2009 UTC

1/* 1/*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG. 2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 * 3 *
4 * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Deliantra team 4 * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team 5 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992,2007 Frank Tore Johansen 6 * Copyright (©) 1992,2007 Frank Tore Johansen
7 * 7 *
8 * Deliantra is free software: you can redistribute it and/or modify 8 * Deliantra is free software: you can redistribute it and/or modify it under
9 * it under the terms of the GNU General Public License as published by 9 * the terms of the Affero GNU General Public License as published by the
10 * the Free Software Foundation, either version 3 of the License, or 10 * Free Software Foundation, either version 3 of the License, or (at your
11 * (at your option) any later version. 11 * option) any later version.
12 * 12 *
13 * This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details. 16 * GNU General Public License for more details.
17 * 17 *
18 * You should have received a copy of the GNU General Public License 18 * You should have received a copy of the Affero GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 * and the GNU General Public License along with this program. If not, see
20 * <http://www.gnu.org/licenses/>.
20 * 21 *
21 * The authors can be reached via e-mail to <support@deliantra.net> 22 * The authors can be reached via e-mail to <support@deliantra.net>
22 */ 23 */
23 24
24/* 25/*
31#include <sys/time.h> 32#include <sys/time.h>
32#include <time.h> 33#include <time.h>
33#include <signal.h> 34#include <signal.h>
34 35
35#include <global.h> 36#include <global.h>
36#include <funcpoint.h>
37#include <material.h> 37#include <material.h>
38#include <object.h>
39
40#include <sys/time.h>
41#include <sys/resource.h>
38 42
39#include <glib.h> 43#include <glib.h>
40 44
41refcnt_base::refcnt_t refcnt_dummy; 45refcnt_base::refcnt_t refcnt_dummy;
42size_t slice_alloc; 46ssize_t slice_alloc;
43rand_gen rndm; 47rand_gen rndm, rmg_rndm;
44 48
45void 49void
46tausworthe_random_generator::seed (uint32_t seed) 50tausworthe_random_generator::seed (uint32_t seed)
47{ 51{
48 state [0] = seed * 69069U; if (state [0] < 2U) state [0] += 2U; 52 state [0] = seed * 69069U; if (state [0] < 2U) state [0] += 2U;
49 state [1] = state [0] * 69069U; if (state [0] < 8U) state [0] += 8U; 53 state [1] = state [0] * 69069U; if (state [0] < 8U) state [0] += 8U;
50 state [2] = state [1] * 69069U; if (state [0] < 16U) state [0] += 16U; 54 state [2] = state [1] * 69069U; if (state [0] < 16U) state [0] += 16U;
51 state [3] = state [2] * 69069U; if (state [0] < 128) state [0] += 128U; 55 state [3] = state [2] * 69069U; if (state [0] < 128U) state [0] += 128U;
52 56
53 for (int i = 11; --i; ) 57 for (int i = 11; --i; )
54 operator ()(); 58 next ();
55} 59}
56 60
57uint32_t 61uint32_t
58tausworthe_random_generator::next () 62tausworthe_random_generator::next ()
59{ 63{
63 state [3] = ((state [3] & 0xFFFFFF80U) << 13U) ^ (((state [3] << 3U) ^ state [3]) >> 12U); 67 state [3] = ((state [3] & 0xFFFFFF80U) << 13U) ^ (((state [3] << 3U) ^ state [3]) >> 12U);
64 68
65 return state [0] ^ state [1] ^ state [2] ^ state [3]; 69 return state [0] ^ state [1] ^ state [2] ^ state [3];
66} 70}
67 71
72template<class generator>
68uint32_t 73uint32_t
69tausworthe_random_generator::get_range (uint32_t num) 74random_number_generator<generator>::get_range (uint32_t num)
70{ 75{
71 return (next () * (uint64_t)num) >> 32U; 76 return (this->next () * (uint64_t)num) >> 32U;
72} 77}
73 78
74// return a number within (min .. max) 79// return a number within (min .. max)
80template<class generator>
75int 81int
76tausworthe_random_generator::get_range (int r_min, int r_max) 82random_number_generator<generator>::get_range (int r_min, int r_max)
77{ 83{
78 return r_min + get_range (max (r_max - r_min + 1, 0)); 84 return r_min + get_range (max (r_max - r_min + 1, 0));
79} 85}
86
87template struct random_number_generator<tausworthe_random_generator>;
88template struct random_number_generator<xorshift_random_generator>;
80 89
81/* 90/*
82 * The random functions here take luck into account when rolling random 91 * The random functions here take luck into account when rolling random
83 * dice or numbers. This function has less of an impact the larger the 92 * dice or numbers. This function has less of an impact the larger the
84 * difference becomes in the random numbers. IE, the effect is lessened 93 * difference becomes in the random numbers. IE, the effect is lessened
94 * not the recipient (ie, the poor slob getting hit). [garbled 20010916] 103 * not the recipient (ie, the poor slob getting hit). [garbled 20010916]
95 */ 104 */
96int 105int
97random_roll (int r_min, int r_max, const object *op, int goodbad) 106random_roll (int r_min, int r_max, const object *op, int goodbad)
98{ 107{
108 r_max = max (r_min, r_max);
109
99 int base = r_max - r_min > 1 ? 20 : 50; /* d2 and d3 are corner cases */ 110 int base = r_max - r_min > 1 ? 20 : 50; /* d2 and d3 are corner cases */
100
101 if (r_max < r_min)
102 {
103 LOG (llevError | logBacktrace, "Calling random_roll with min=%d max=%d\n", r_min, r_max);
104 return r_min;
105 }
106 111
107 if (op->type == PLAYER) 112 if (op->type == PLAYER)
108 { 113 {
109 int luck = op->stats.luck; 114 int luck = op->stats.luck;
110 115
120/* 125/*
121 * This is a 64 bit version of random_roll above. This is needed 126 * This is a 64 bit version of random_roll above. This is needed
122 * for exp loss calculations for players changing religions. 127 * for exp loss calculations for players changing religions.
123 */ 128 */
124sint64 129sint64
125random_roll64 (sint64 min, sint64 max, const object *op, int goodbad) 130random_roll64 (sint64 r_min, sint64 r_max, const object *op, int goodbad)
126{ 131{
127 sint64 omin = min; 132 sint64 omin = r_min;
128 sint64 diff = max - min + 1; 133 sint64 range = max (0, r_max - r_min + 1);
129 int base = diff > 2 ? 20 : 50; /* d2 and d3 are corner cases */ 134 int base = range > 2 ? 20 : 50; /* d2 and d3 are corner cases */
130
131 if (diff < 0)
132 {
133 LOG (llevError | logBacktrace, "Calling random_roll64 with min=%" PRId64 " max=%" PRId64 "\n", min, max);
134 return (min); /* avoids a float exception */
135 }
136 135
137 /* 136 /*
138 * Make a call to get two 32 bit unsigned random numbers, and just to 137 * Make a call to get two 32 bit unsigned random numbers, and just to
139 * a little bitshifting. 138 * a little bitshifting.
140 */ 139 */
141 sint64 ran = (sint64) rndm.next () ^ ((sint64) rndm.next () << 31); 140 sint64 ran = (sint64) rndm.next () ^ ((sint64) rndm.next () << 31);
142 141
143 if (op->type != PLAYER) 142 if (op->type != PLAYER)
144 return ((ran % diff) + min); 143 return ((ran % range) + r_min);
145 144
146 int luck = op->stats.luck; 145 int luck = op->stats.luck;
147 146
148 if (rndm (base) < MIN (10, abs (luck))) 147 if (rndm (base) < min (10, abs (luck)))
149 { 148 {
150 /* we have a winner */ 149 /* we have a winner */
151 ((luck > 0) ? (luck = 1) : (luck = -1)); 150 ((luck > 0) ? (luck = 1) : (luck = -1));
152 diff -= luck; 151 range -= luck;
153 if (diff < 1) 152 if (range < 1)
154 return (omin); /*check again */ 153 return (omin); /*check again */
155 154
156 ((goodbad) ? (min += luck) : (diff)); 155 ((goodbad) ? (r_min += luck) : (range));
157 156
158 return (MAX (omin, MIN (max, (ran % diff) + min))); 157 return (max (omin, min (r_max, (ran % range) + r_min)));
159 } 158 }
160 159
161 return ran % diff + min; 160 return ran % range + r_min;
162} 161}
163 162
164/* 163/*
165 * Roll a number of dice (2d3, 4d6). Uses op to determine luck, 164 * Roll a number of dice (2d3, 4d6). Uses op to determine luck,
166 * If goodbad is non-zero, luck increases the roll, if zero, it decreases. 165 * If goodbad is non-zero, luck increases the roll, if zero, it decreases.
208} 207}
209 208
210/* convert materialname to materialtype_t */ 209/* convert materialname to materialtype_t */
211 210
212materialtype_t * 211materialtype_t *
213name_to_material (const shstr &name) 212name_to_material (const shstr_cmp name)
214{ 213{
215 for (materialtype_t *mt = materialt; mt && mt->next; mt = mt->next) 214 for (materialtype_t *mt = materialt; mt; mt = mt->next)
216 if (name == mt->name) 215 if (name == mt->name)
217 return mt; 216 return mt;
218 217
219 return 0; 218 return 0;
220} 219}
226transmute_materialname (object *op, const object *change) 225transmute_materialname (object *op, const object *change)
227{ 226{
228 materialtype_t *mt; 227 materialtype_t *mt;
229 int j; 228 int j;
230 229
231 if (op->materialname == NULL) 230 if (!op->materialname)
232 return; 231 return;
233 232
234 if (change->materialname != NULL && strcmp (op->materialname, change->materialname)) 233 if (op->materialname != change->materialname)
235 return; 234 return;
236 235
237 if (!op->is_armor ()) 236 if (!op->is_armor ())
238 return; 237 return;
239 238
259void 258void
260set_materialname (object *op, int difficulty, materialtype_t *nmt) 259set_materialname (object *op, int difficulty, materialtype_t *nmt)
261{ 260{
262 materialtype_t *mt, *lmt; 261 materialtype_t *mt, *lmt;
263 262
264 if (op->materialname != NULL) 263 if (!op->materialname)
265 return; 264 return;
266 265
267 if (nmt == NULL) 266 if (nmt)
267 lmt = nmt;
268 else
268 { 269 {
269 lmt = NULL; 270 lmt = 0;
270 271
271 for (mt = materialt; mt && mt->next; mt = mt->next) 272 for (mt = materialt; mt; mt = mt->next)
272 if (op->materials & mt->material && rndm (1, 100) <= mt->chance && 273 if (op->materials & mt->material && rndm (1, 100) <= mt->chance &&
273 difficulty >= mt->difficulty && (op->magic >= mt->magic || mt->magic == 0)) 274 difficulty >= mt->difficulty && (op->magic >= mt->magic || mt->magic == 0))
274 { 275 {
275 lmt = mt; 276 lmt = mt;
276 if (!(op->is_weapon () || op->is_armor ())) 277 if (!(op->is_weapon () || op->is_armor ()))
277 break; 278 break;
278 } 279 }
279 } 280 }
280 else
281 lmt = nmt;
282 281
283 if (lmt != NULL) 282 if (lmt)
284 { 283 {
285 if (op->stats.dam && op->is_weapon ()) 284 if (op->stats.dam && op->is_weapon ())
286 { 285 {
287 op->stats.dam += lmt->damage; 286 op->stats.dam += lmt->damage;
288 if (op->stats.dam < 1) 287 if (op->stats.dam < 1)
450 strcpy (input, tmp); 449 strcpy (input, tmp);
451 450
452 return; 451 return;
453} 452}
454 453
454/******************************************************************************/
455
456/* Checks a player-provided string which will become the msg property of
457 * an object for dangerous input.
458 */
459bool
460msg_is_safe (const char *msg)
461{
462 bool safe = true;
463
464 /* Trying to cheat by getting data into the object */
465 if (!strncmp (msg, "endmsg", sizeof ("endmsg") - 1)
466 || strstr (msg, "\nendmsg"))
467 safe = false;
468
469 /* Trying to make the object talk, and potentially access arbitrary code */
470 if (object::msg_has_dialogue (msg))
471 safe = false;
472
473 return safe;
474}
475
455///////////////////////////////////////////////////////////////////////////// 476/////////////////////////////////////////////////////////////////////////////
456 477
457void 478void
458fork_abort (const char *msg) 479fork_abort (const char *msg)
459{ 480{
460 if (!fork ()) 481 if (!fork ())
461 { 482 {
483 signal (SIGINT , SIG_IGN);
484 signal (SIGTERM, SIG_IGN);
462 signal (SIGABRT, SIG_DFL); 485 signal (SIGABRT, SIG_IGN);
486
487 signal (SIGSEGV, SIG_DFL);
488 signal (SIGBUS , SIG_DFL);
489 signal (SIGILL , SIG_DFL);
490 signal (SIGTRAP, SIG_DFL);
491
463 // try to put corefiles into a subdirectory, if existing, to allow 492 // try to put corefiles into a subdirectory, if existing, to allow
464 // an administrator to reduce the I/O load. 493 // an administrator to reduce the I/O load.
465 chdir ("cores"); 494 chdir ("cores");
495
496 // try to detach us from as many external dependencies as possible
497 // as coredumping can take time by closing all fd's.
498 {
499 struct rlimit lim;
500
501 if (getrlimit (RLIMIT_NOFILE, &lim))
502 lim.rlim_cur = 1024;
503
504 for (int i = 0; i < lim.rlim_cur; ++i)
505 close (i);
506 }
507
508 {
509 sigset_t empty;
510 sigemptyset (&empty);
511 sigprocmask (SIG_SETMASK, &empty, 0);
512 }
513
514 // try to coredump with SIGTRAP
515 kill (getpid (), SIGTRAP);
466 abort (); 516 abort ();
467 } 517 }
468 518
469 LOG (llevError, "fork abort: %s\n", msg); 519 LOG (llevError, "fork abort: %s\n", msg);
470} 520}
471 521
472void *salloc_ (int n) throw (std::bad_alloc) 522void *salloc_ (int n) throw (std::bad_alloc)
473{ 523{
474#ifdef PREFER_MALLOC
475 void *ptr = malloc (n);
476#else
477 slice_alloc += n;
478 void *ptr = g_slice_alloc (n); 524 void *ptr = g_slice_alloc (n);
479#endif
480 525
481 if (!ptr) 526 if (!ptr)
482 throw std::bad_alloc (); 527 throw std::bad_alloc ();
483 528
529 slice_alloc += n;
484 return ptr; 530 return ptr;
485} 531}
486 532
487void *salloc_ (int n, void *src) throw (std::bad_alloc) 533void *salloc_ (int n, void *src) throw (std::bad_alloc)
488{ 534{
496 return ptr; 542 return ptr;
497} 543}
498 544
499/******************************************************************************/ 545/******************************************************************************/
500 546
501#ifdef DEBUG_SALLOC 547#if DEBUG_SALLOC
502 548
503#define MAGIC 0xa1b2c35543deadL 549#define MAGIC 0xa1b2c35543deadLL
504 550
505void *g_slice_alloc (unsigned long size) 551void *g_slice_alloc (unsigned long size)
506{ 552{
507 unsigned long *p = (unsigned long *) (g_slice_alloc)(size + sizeof (unsigned long)); 553 unsigned long *p = (unsigned long *) (g_slice_alloc)(size + sizeof (unsigned long));
508 *p++ = size ^ MAGIC; 554 *p++ = size ^ MAGIC;
515 return memset (g_slice_alloc (size), 0, size); 561 return memset (g_slice_alloc (size), 0, size);
516} 562}
517 563
518void g_slice_free1 (unsigned long size, void *ptr) 564void g_slice_free1 (unsigned long size, void *ptr)
519{ 565{
566 //fprintf (stderr, "g_slice_free %ld %p\n", size, ptr);//D
520 if (expect_true (ptr)) 567 if (expect_true (ptr))
521 { 568 {
522 //fprintf (stderr, "g_slice_free %ld %p\n", size, ptr);//D
523 unsigned long *p = (unsigned long *)ptr; 569 unsigned long *p = (unsigned long *)ptr;
524 unsigned long s = *--p ^ MAGIC; 570 unsigned long s = *--p ^ MAGIC;
525 571
526 if ((*p ^ MAGIC) != size) 572 if (size != (unsigned long)(*p ^ MAGIC))
573 {
527 LOG (logBacktrace | llevError, "slice free size (%lx) doesn't match alloc size (%lx)\n", size, s); 574 LOG (logBacktrace | llevError, "slice free size (%lx) doesn't match alloc size (%lx)\n", size, s);
575 abort ();
576 }
528 577
529 *p = MAGIC; 578 *p = MAGIC;
530 579
531 (g_slice_free1)(s + sizeof (unsigned long), p); 580 (g_slice_free1)(s + sizeof (unsigned long), p);
532 } 581 }
534 583
535#endif 584#endif
536 585
537/******************************************************************************/ 586/******************************************************************************/
538 587
588int
539void assign (char *dst, const char *src, int maxlen) 589assign (char *dst, const char *src, int maxsize)
540{ 590{
541 if (!src) 591 if (!src)
542 src = ""; 592 src = "";
543 593
544 int len = strlen (src); 594 int len = strlen (src);
545 595
546 if (len >= maxlen - 1) 596 if (len >= maxsize)
547 { 597 {
548 if (maxlen <= 4) 598 if (maxsize <= 4)
549 { 599 {
550 memset (dst, '.', maxlen - 1); 600 memset (dst, '.', maxsize - 2);
551 dst [maxlen - 1] = 0; 601 dst [maxsize - 1] = 0;
552 } 602 }
553 else 603 else
554 { 604 {
555 memcpy (dst, src, maxlen - 4); 605 memcpy (dst, src, maxsize - 4);
556 memcpy (dst + maxlen - 4, "...", 4); 606 memcpy (dst + maxsize - 4, "...", 4);
557 } 607 }
608
609 len = maxsize;
558 } 610 }
559 else 611 else
560 memcpy (dst, src, len + 1); 612 memcpy (dst, src, ++len);
561}
562 613
563const char * 614 return len;
615}
616
617char *
618vformat (const char *format, va_list ap)
619{
620 static dynbuf_text buf; buf.clear ();
621 buf.vprintf (format, ap);
622 return buf;
623}
624
625char *
564format (const char *format, ...) 626format (const char *format, ...)
565{ 627{
566 static dynbuf_text buf;
567
568 buf.clear ();
569
570 va_list ap; 628 va_list ap;
571 va_start (ap, format); 629 va_start (ap, format);
572 buf.vprintf (format, ap); 630 char *buf = vformat (format, ap);
573 va_end (ap); 631 va_end (ap);
574 632
575 return buf; 633 return buf;
576} 634}
577 635
648 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, 706 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
649 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, 707 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
650 0x2d02ef8dL 708 0x2d02ef8dL
651}; 709};
652 710
711void thread::start (void *(*start_routine)(void *), void *arg)
712{
713 pthread_attr_t attr;
714
715 pthread_attr_init (&attr);
716 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
717 pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN < sizeof (long) * 4096
718 ? sizeof (long) * 4096 : PTHREAD_STACK_MIN);
719#ifdef PTHREAD_SCOPE_PROCESS
720 pthread_attr_setscope (&attr, PTHREAD_SCOPE_PROCESS);
721#endif
722
723 sigset_t fullsigset, oldsigset;
724 sigfillset (&fullsigset);
725
726 pthread_sigmask (SIG_SETMASK, &fullsigset, &oldsigset);
727
728 if (pthread_create (&id, &attr, start_routine, arg))
729 cleanup ("unable to create a new thread");
730
731 pthread_sigmask (SIG_SETMASK, &oldsigset, 0);
732}
733

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines