ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/init.C
Revision: 1.86
Committed: Mon Dec 17 02:07:15 2012 UTC (11 years, 5 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-3_1
Changes since 1.85: +23 -8 lines
Log Message:
sigfpe handling

File Contents

# User Rev Content
1 elmex 1.1 /*
2 root 1.59 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 root 1.85 *
4 root 1.84 * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 root 1.78 * Copyright (©) 2002 Mark Wedel & Crossfire Development Team
6     * Copyright (©) 1992 Frank Tore Johansen
7 root 1.85 *
8 root 1.71 * Deliantra is free software: you can redistribute it and/or modify it under
9     * the terms of the Affero GNU General Public License as published by the
10     * Free Software Foundation, either version 3 of the License, or (at your
11     * option) any later version.
12 root 1.85 *
13 root 1.56 * 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 root 1.85 *
18 root 1.71 * You should have received a copy of the Affero GNU General Public License
19     * and the GNU General Public License along with this program. If not, see
20     * <http://www.gnu.org/licenses/>.
21 root 1.85 *
22 root 1.59 * The authors can be reached via e-mail to <support@deliantra.net>
23 pippijn 1.34 */
24 elmex 1.1
25     #include <global.h>
26     #include <material.h>
27 root 1.22 #include <sproto.h>
28 elmex 1.1
29     /* This loads the settings file. There could be debate whether this should
30     * be here or in the common directory - but since only the server needs this
31     * information, having it here probably makes more sense.
32     */
33 root 1.66 void
34 root 1.76 load_settings ()
35 elmex 1.1 {
36 root 1.81 object_thawer thawer (settings.confdir, "settings");
37 root 1.80
38     if (!thawer)
39 root 1.9 {
40 root 1.43 LOG (llevError, "Error: No settings file found\n");
41     exit (1);
42 elmex 1.1 }
43 root 1.43
44 root 1.80 while (thawer.kw)
45 root 1.9 {
46 root 1.80 const char *buf = thawer.kw_str;
47     const char *cp = thawer.value_nn;
48 root 1.9
49 root 1.80 if (!strcmp (buf, "not_permadeth"))
50 root 1.9 {
51 root 1.80 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
52 root 1.9 {
53     settings.not_permadeth = TRUE;
54     }
55 root 1.80 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
56 root 1.9 {
57     settings.not_permadeth = FALSE;
58     }
59     else
60     {
61     LOG (llevError, "load_settings: Unknown value for not_permadeth" ": %s\n", cp);
62     }
63     }
64 root 1.80 else if (!strcmp (buf, "resurrection"))
65 root 1.9 {
66 root 1.80 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
67 root 1.9 {
68     settings.resurrection = TRUE;
69     }
70 root 1.80 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
71 root 1.9 {
72     settings.resurrection = FALSE;
73     }
74     else
75     {
76     LOG (llevError, "load_settings: Unknown value for resurrection" ": %s\n", cp);
77     }
78     }
79 root 1.80 else if (!strcmp (buf, "set_title"))
80 root 1.9 {
81 root 1.80 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
82 root 1.9 {
83     settings.set_title = TRUE;
84     }
85 root 1.80 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
86 root 1.9 {
87     settings.set_title = FALSE;
88     }
89     else
90     {
91     LOG (llevError, "load_settings: Unknown value for set_title" ": %s\n", cp);
92     }
93     }
94 root 1.80 else if (!strcmp (buf, "search_items"))
95 root 1.9 {
96 root 1.80 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
97 root 1.9 {
98     settings.search_items = TRUE;
99     }
100 root 1.80 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
101 root 1.9 {
102     settings.search_items = FALSE;
103     }
104     else
105     {
106     LOG (llevError, "load_settings: Unknown value for search_items" ": %s\n", cp);
107     }
108     }
109 root 1.80 else if (!strcmp (buf, "spell_encumbrance"))
110 root 1.9 {
111 root 1.80 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
112 root 1.9 {
113     settings.spell_encumbrance = TRUE;
114     }
115 root 1.80 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
116 root 1.9 {
117     settings.spell_encumbrance = FALSE;
118     }
119     else
120     {
121     LOG (llevError, "load_settings: Unknown value for " "spell_encumbrance: %s\n", cp);
122     }
123     }
124 root 1.80 else if (!strcmp (buf, "spell_failure_effects"))
125 root 1.9 {
126 root 1.80 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
127 root 1.9 {
128     settings.spell_failure_effects = TRUE;
129     }
130 root 1.80 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
131 root 1.9 {
132     settings.spell_failure_effects = FALSE;
133     }
134     else
135     {
136     LOG (llevError, "load_settings: Unknown value for " "spell_failure_effects: %s\n", cp);
137     }
138     }
139 root 1.80 else if (!strcmp (buf, "spellpoint_level_depend"))
140 root 1.9 {
141 root 1.80 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
142 root 1.9 {
143     settings.spellpoint_level_depend = TRUE;
144     }
145 root 1.80 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
146 root 1.9 {
147     settings.spellpoint_level_depend = FALSE;
148     }
149     else
150     {
151     LOG (llevError, "load_settings: Unknown value for " "spellpoint_level_depend: %s\n", cp);
152     }
153     }
154 root 1.80 else if (!strcmp (buf, "stat_loss_on_death"))
155 root 1.9 {
156 root 1.80 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
157 root 1.9 {
158     settings.stat_loss_on_death = TRUE;
159     }
160 root 1.80 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
161 root 1.9 {
162     settings.stat_loss_on_death = FALSE;
163     }
164     else
165     {
166     LOG (llevError, "load_settings: Unknown value for " "stat_loss_on_death: %s\n", cp);
167     }
168     }
169 root 1.80 else if (!strcmp (buf, "use_permanent_experience"))
170 root 1.9 {
171     LOG (llevError, "use_permanent_experience is deprecated, use" "permenent_experience_percentage instead\n");
172     }
173 root 1.80 else if (!strcmp (buf, "permanent_experience_percentage"))
174 root 1.9 {
175     int val = atoi (cp);
176    
177     if (val < 0 || val > 100)
178     LOG (llevError, "load_settings: permenent_experience_percentage" "must be between 0 and 100, %d is invalid\n", val);
179     else
180     settings.permanent_exp_ratio = val;
181     }
182 root 1.80 else if (!strcmp (buf, "death_penalty_percentage"))
183 root 1.9 {
184     int val = atoi (cp);
185    
186     if (val < 0 || val > 100)
187     LOG (llevError, "load_settings: death_penalty_percentage" "must be between 0 and 100, %d is invalid\n", val);
188     else
189     settings.death_penalty_ratio = val;
190     }
191 root 1.80 else if (!strcmp (buf, "death_penalty_levels"))
192 root 1.9 {
193     int val = atoi (cp);
194    
195     if (val < 0 || val > 255)
196     LOG (llevError, "load_settings: death_penalty_levels" "can not be negative, %d is invalid\n", val);
197     else
198     settings.death_penalty_level = val;
199     }
200 root 1.80 else if (!strcmp (buf, "balanced_stat_loss"))
201 root 1.9 {
202 root 1.80 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
203 root 1.9 {
204     settings.balanced_stat_loss = TRUE;
205     }
206 root 1.80 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
207 root 1.9 {
208     settings.balanced_stat_loss = FALSE;
209     }
210     else
211     {
212     LOG (llevError, "load_settings: Unknown value for " "balanced_stat_loss: %s\n", cp);
213     }
214     }
215 root 1.80 else if (!strcmp (buf, "simple_exp"))
216 root 1.9 {
217 root 1.80 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
218 root 1.9 {
219     settings.simple_exp = TRUE;
220     }
221 root 1.80 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
222 root 1.9 {
223     settings.simple_exp = FALSE;
224     }
225     else
226     {
227     LOG (llevError, "load_settings: Unknown value for simple_exp: %s\n", cp);
228     }
229     }
230 root 1.80 else if (!strcmp (buf, "item_power_factor"))
231 root 1.9 {
232     float tmp = atof (cp);
233    
234     if (tmp < 0)
235     LOG (llevError, "load_settings: item_power_factor must be a positive number (%f < 0)\n", tmp);
236     else
237     settings.item_power_factor = tmp;
238     }
239 root 1.80 else if (!strcmp (buf, "pk_luck_penalty"))
240 root 1.9 {
241     sint16 val = atoi (cp);
242    
243     if (val < -100 || val > 100)
244     LOG (llevError, "load_settings: pk_luck_penalty must be between -100 and 100" ", %d is invalid\n", val);
245     else
246     settings.pk_luck_penalty = val;
247     }
248 root 1.80 else if (!strcmp (buf, "set_friendly_fire"))
249 root 1.9 {
250     int val = atoi (cp);
251 elmex 1.1
252 root 1.9 if (val < 0 || val > 100)
253     LOG (llevError, "load_settings: set_friendly_fire must be between 0 an 100" ", %d is invalid\n", val);
254     else
255     settings.set_friendly_fire = val;
256     }
257 root 1.80 else if (!strcmp (buf, "armor_max_enchant"))
258 root 1.9 {
259     int max_e = atoi (cp);
260    
261     if (max_e <= 0)
262     LOG (llevError, "load_settings: armor_max_enchant is %d\n", max_e);
263     else
264 elmex 1.1 settings.armor_max_enchant = max_e;
265 root 1.9 }
266 root 1.80 else if (!strcmp (buf, "armor_weight_reduction"))
267 root 1.9 {
268     int wr = atoi (cp);
269    
270     if (wr < 0)
271     LOG (llevError, "load_settings: armor_weight_reduction is %d\n", wr);
272     else
273 elmex 1.1 settings.armor_weight_reduction = wr;
274     }
275 root 1.80 else if (!strcmp (buf, "armor_weight_linear"))
276 root 1.9 {
277 root 1.80 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
278 root 1.9 {
279     settings.armor_weight_linear = TRUE;
280     }
281 root 1.80 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
282 root 1.9 {
283     settings.armor_weight_linear = FALSE;
284     }
285     else
286     {
287     LOG (llevError, "load_settings: unknown value for armor_weight_linear: %s\n", cp);
288     }
289    
290     }
291 root 1.80 else if (!strcmp (buf, "armor_speed_improvement"))
292 root 1.9 {
293     int wr = atoi (cp);
294 elmex 1.1
295 root 1.9 if (wr < 0)
296     LOG (llevError, "load_settings: armor_speed_improvement is %d\n", wr);
297     else
298 elmex 1.1 settings.armor_speed_improvement = wr;
299     }
300 root 1.80 else if (!strcmp (buf, "armor_speed_linear"))
301 root 1.9 {
302 root 1.80 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
303 root 1.9 {
304     settings.armor_speed_linear = TRUE;
305     }
306 root 1.80 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
307 root 1.9 {
308     settings.armor_speed_linear = FALSE;
309     }
310     else
311     {
312     LOG (llevError, "load_settings: unknown value for armor_speed_linear: %s\n", cp);
313     }
314    
315     }
316     else
317 root 1.80 thawer.parse_error ("settings file");
318    
319     thawer.next ();
320 elmex 1.1 }
321     }
322    
323     /*
324     * init() is called only once, when starting the program.
325     */
326 root 1.9 void
327     init (int argc, char **argv)
328     {
329 root 1.37 init_done = 0; /* Must be done before init_signal() */
330 root 1.36
331 root 1.42 init_environ ();
332 root 1.14 cfperl_init ();
333 root 1.9 init_done = 1;
334 elmex 1.1 }
335    
336     /* Signal handlers: */
337    
338 root 1.48 static void
339 root 1.33 rec_sigabrt (int i)
340     {
341     signal (SIGABRT, SIG_DFL);
342    
343     LOG (llevError, "SIGABRT received.\n");
344     cleanup ("SIGABRT received", 1);
345     }
346    
347 root 1.48 static void
348 root 1.86 rec_sigquit (int i)
349     {
350     signal (SIGQUIT, SIG_IGN);
351    
352     LOG (llevInfo, "SIGQUIT received\n");
353     cleanup ("SIGQUIT received", 1);
354     }
355    
356     static void
357 root 1.9 rec_sigsegv (int i)
358     {
359 root 1.33 signal (SIGSEGV, SIG_DFL);
360    
361 root 1.21 LOG (llevError, "SIGSEGV received.\n");
362 root 1.29 cleanup ("SIGSEGV received", 1);
363 elmex 1.1 }
364    
365 root 1.48 static void
366 root 1.86 rec_sigbus (int i)
367 root 1.9 {
368 root 1.86 signal (SIGBUS, SIG_DFL);
369 root 1.33
370 root 1.86 LOG (llevError, "SIGBUS received\n");
371     cleanup ("SIGBUS received", 1);
372 elmex 1.1 }
373    
374 root 1.48 static void
375 root 1.86 rec_sigfpe (int i)
376 root 1.9 {
377 root 1.86 signal (SIGFPE, SIG_DFL);
378 root 1.33
379 root 1.86 LOG (llevError, "SIGFPE received.\n");
380     cleanup ("SIGFPE received", 1);
381 elmex 1.1 }
382    
383 root 1.9 void
384 root 1.48 reset_signals ()
385     {
386     signal (SIGABRT, SIG_DFL);
387     signal (SIGQUIT, SIG_DFL);
388     signal (SIGSEGV, SIG_DFL);
389 root 1.86 #ifdef SIGBUS
390 root 1.48 signal (SIGBUS , SIG_DFL);
391 root 1.86 #endif
392     signal (SIGFPE , SIG_DFL);
393 root 1.48 signal (SIGINT , SIG_DFL);
394     signal (SIGTERM, SIG_DFL);
395     }
396    
397     void
398 root 1.76 init_signals ()
399 root 1.9 {
400 root 1.37 // large stack, but it's important data we want to save, and it is not usually
401     // being physically allocated anyways
402     const size_t stacksize = 8 * 1024 * 1024 + SIGSTKSZ;
403    
404     stack_t ss;
405     ss.ss_sp = malloc (stacksize);
406     ss.ss_flags = 0;
407     ss.ss_size = stacksize;
408     sigaltstack (&ss, 0);
409    
410     struct sigaction sa;
411    
412     sigfillset (&sa.sa_mask);
413 root 1.49 sa.sa_flags = SA_RESTART;
414 root 1.37
415     sa.sa_handler = SIG_IGN; sigaction (SIGPIPE, &sa, 0);
416     sa.sa_handler = rec_sigabrt; sigaction (SIGABRT, &sa, 0);
417     sa.sa_handler = rec_sigquit; sigaction (SIGQUIT, &sa, 0);
418 root 1.86 #ifdef SIGBUS
419 root 1.49 sa.sa_handler = rec_sigbus; sigaction (SIGBUS, &sa, 0);
420 root 1.86 #endif
421     sa.sa_handler = rec_sigfpe; sigaction (SIGFPE, &sa, 0);
422 root 1.49
423     sa.sa_flags |= SA_ONSTACK;
424 root 1.37 sa.sa_handler = rec_sigsegv; sigaction (SIGSEGV, &sa, 0);
425 elmex 1.1 }
426    
427 root 1.74 static racelink *
428     get_racelist ()
429     {
430     racelink *list = new racelink;
431    
432     list->name = 0;
433     list->nrof = 0;
434     list->next = 0;
435     list->member = get_objectlink ();
436    
437     return list;
438     }
439    
440     racelink *
441     find_racelink (const char *name)
442     {
443     if (name)
444     for (racelink *link = first_race; link; link = link->next)
445     if (!link->name || !strcmp (name, link->name))
446     return link;
447    
448     return 0;
449     }
450    
451     static void
452     add_to_racelist (const char *race_name, object *op)
453     {
454     racelink *race;
455    
456     if (!op || !race_name)
457     return;
458    
459     race = find_racelink (race_name);
460    
461     if (!race)
462     { /* add in a new race list */
463     race = get_racelist ();
464     race->next = first_race;
465     first_race = race;
466     race->name = race_name;
467     }
468    
469     if (race->member->ob)
470     {
471     objectlink *tmp = get_objectlink ();
472    
473     tmp->next = race->member;
474     race->member = tmp;
475     }
476    
477     race->nrof++;
478     race->member->ob = op;
479     }
480    
481 elmex 1.1 /* init_races() - reads the races file in the lib/ directory, then
482     * overwrites old 'race' entries. This routine allow us to quickly
483     * re-configure the 'alignment' of monsters, objects. Useful for
484     * putting together lists of creatures, etc that belong to gods.
485     */
486 root 1.74 static void
487 root 1.76 init_races ()
488 elmex 1.8 {
489 elmex 1.1 FILE *file;
490     char race[MAX_BUF], fname[MAX_BUF], buf[MAX_BUF], *cp, variable[MAX_BUF];
491 elmex 1.8 archetype *mon = NULL;
492     static int init_done = 0;
493 elmex 1.1
494 elmex 1.8 if (init_done)
495 elmex 1.1 return;
496 elmex 1.8 init_done = 1;
497 root 1.10 first_race = 0;
498 elmex 1.1
499 elmex 1.8 sprintf (fname, "%s/races", settings.datadir);
500 pippijn 1.25 LOG (llevDebug, "Reading races from %s...\n", fname);
501 elmex 1.8 if (!(file = fopen (fname, "r")))
502     {
503 root 1.9 LOG (llevError, "Cannot open races file %s: %s\n", fname, strerror (errno));
504 elmex 1.8 return;
505 elmex 1.1 }
506 elmex 1.8
507     while (fgets (buf, MAX_BUF, file) != NULL)
508     {
509     int set_race = 1, set_list = 1;
510 root 1.9
511 elmex 1.8 if (*buf == '#')
512     continue;
513 root 1.10
514 elmex 1.8 if ((cp = strchr (buf, '\n')) != NULL)
515     *cp = '\0';
516 root 1.10
517 elmex 1.8 cp = buf;
518     while (*cp == ' ' || *cp == '!' || *cp == '@')
519     {
520 root 1.65 if (*cp == '!') set_race = 0;
521     if (*cp == '@') set_list = 0;
522    
523 elmex 1.8 cp++;
524     }
525 root 1.10
526 elmex 1.8 if (sscanf (cp, "RACE %s", variable))
527 root 1.40 /* set new race value */
528     strcpy (race, variable);
529 elmex 1.8 else
530     {
531     char *cp1;
532 root 1.9
533 elmex 1.8 /* Take out beginning spaces */
534     for (cp1 = cp; *cp1 == ' '; cp1++)
535     ;
536     /* Remove newline and trailing spaces */
537     for (cp1 = cp + strlen (cp) - 1; *cp1 == '\n' || *cp1 == ' '; cp1--)
538     {
539     *cp1 = '\0';
540     if (cp == cp1)
541     break;
542     }
543    
544     if (cp[strlen (cp) - 1] == '\n')
545     cp[strlen (cp) - 1] = '\0';
546 root 1.10
547 elmex 1.8 /* set creature race to race value */
548 root 1.12 if ((mon = archetype::find (cp)) == NULL)
549 pippijn 1.25 LOG (llevError, "Creature %s in race file lacks archetype\n", cp);
550 elmex 1.8 else
551     {
552 root 1.70 if (set_race && (!mon->race || strcmp (&mon->race, race)))
553 elmex 1.8 {
554 root 1.54 if (mon->race)
555     LOG (llevDebug, "Resetting race to %s from %s for archetype %s\n", race, &mon->race, &mon->archname);
556 root 1.10
557 root 1.54 mon->race = race;
558 elmex 1.1 }
559 root 1.10
560 elmex 1.8 /* if the arch is a monster, add it to the race list */
561 root 1.79 if (set_list && mon->flag [FLAG_MONSTER])
562 root 1.54 add_to_racelist (race, mon);
563 elmex 1.8 }
564 elmex 1.1 }
565     }
566 root 1.10
567 elmex 1.8 fclose (file);
568     LOG (llevDebug, "done.\n");
569 elmex 1.1 }
570    
571 root 1.9 void
572 root 1.76 init_beforeplay ()
573 root 1.9 {
574 root 1.74 init_artifacts (); /* If not called before, reads all artifacts from file */
575     init_races (); /* overwrite race designations using entries in lib/races file */
576     init_gods (); /* init linked list of gods from archs */
577     init_readable (); /* inits useful arrays for readable texts */
578     init_formulae (); /* If not called before, reads formulae from file */
579 elmex 1.1 }
580