ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/init.C
Revision: 1.89
Committed: Wed Dec 5 19:31:26 2018 UTC (5 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.88: +1 -1 lines
Log Message:
improve, not fix, some sscanf madness, probably introducing more bugs

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