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, 5 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

# Content
1 /*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 *
4 * Copyright (©) 2017,2018 Marc Alexander Lehmann / the Deliantra team
5 * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
6 * Copyright (©) 2002 Mark Wedel & Crossfire Development Team
7 * Copyright (©) 1992 Frank Tore Johansen
8 *
9 * 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 *
14 * 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 *
19 * 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 *
23 * The authors can be reached via e-mail to <support@deliantra.net>
24 */
25
26 #include <global.h>
27 #include <material.h>
28 #include <sproto.h>
29
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 void
35 load_settings ()
36 {
37 object_thawer thawer (settings.confdir, "settings");
38
39 if (!thawer)
40 {
41 LOG (llevError, "Error: No settings file found\n");
42 exit (1);
43 }
44
45 while (thawer.kw)
46 {
47 const char *buf = thawer.kw_str;
48 const char *cp = thawer.value_nn;
49
50 if (!strcmp (buf, "not_permadeth"))
51 {
52 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
53 {
54 settings.not_permadeth = TRUE;
55 }
56 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
57 {
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 else if (!strcmp (buf, "resurrection"))
66 {
67 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
68 {
69 settings.resurrection = TRUE;
70 }
71 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
72 {
73 settings.resurrection = FALSE;
74 }
75 else
76 {
77 LOG (llevError, "load_settings: Unknown value for resurrection" ": %s\n", cp);
78 }
79 }
80 else if (!strcmp (buf, "set_title"))
81 {
82 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
83 {
84 settings.set_title = TRUE;
85 }
86 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
87 {
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 else if (!strcmp (buf, "search_items"))
96 {
97 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
98 {
99 settings.search_items = TRUE;
100 }
101 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
102 {
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 else if (!strcmp (buf, "spell_encumbrance"))
111 {
112 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
113 {
114 settings.spell_encumbrance = TRUE;
115 }
116 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
117 {
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 else if (!strcmp (buf, "spell_failure_effects"))
126 {
127 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
128 {
129 settings.spell_failure_effects = TRUE;
130 }
131 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
132 {
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 else if (!strcmp (buf, "spellpoint_level_depend"))
141 {
142 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
143 {
144 settings.spellpoint_level_depend = TRUE;
145 }
146 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
147 {
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 else if (!strcmp (buf, "stat_loss_on_death"))
156 {
157 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
158 {
159 settings.stat_loss_on_death = TRUE;
160 }
161 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
162 {
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 else if (!strcmp (buf, "use_permanent_experience"))
171 {
172 LOG (llevError, "use_permanent_experience is deprecated, use" "permenent_experience_percentage instead\n");
173 }
174 else if (!strcmp (buf, "permanent_experience_percentage"))
175 {
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 else if (!strcmp (buf, "death_penalty_percentage"))
184 {
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 else if (!strcmp (buf, "death_penalty_levels"))
193 {
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 else if (!strcmp (buf, "balanced_stat_loss"))
202 {
203 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
204 {
205 settings.balanced_stat_loss = TRUE;
206 }
207 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
208 {
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 else if (!strcmp (buf, "simple_exp"))
217 {
218 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
219 {
220 settings.simple_exp = TRUE;
221 }
222 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
223 {
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 else if (!strcmp (buf, "item_power_factor"))
232 {
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 else if (!strcmp (buf, "pk_luck_penalty"))
241 {
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 else if (!strcmp (buf, "set_friendly_fire"))
250 {
251 int val = atoi (cp);
252
253 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 else if (!strcmp (buf, "armor_max_enchant"))
259 {
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 settings.armor_max_enchant = max_e;
266 }
267 else if (!strcmp (buf, "armor_weight_reduction"))
268 {
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 settings.armor_weight_reduction = wr;
275 }
276 else if (!strcmp (buf, "armor_weight_linear"))
277 {
278 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
279 {
280 settings.armor_weight_linear = TRUE;
281 }
282 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
283 {
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 else if (!strcmp (buf, "armor_speed_improvement"))
293 {
294 int wr = atoi (cp);
295
296 if (wr < 0)
297 LOG (llevError, "load_settings: armor_speed_improvement is %d\n", wr);
298 else
299 settings.armor_speed_improvement = wr;
300 }
301 else if (!strcmp (buf, "armor_speed_linear"))
302 {
303 if (!strcmp (cp, "on") || !strcmp (cp, "true"))
304 {
305 settings.armor_speed_linear = TRUE;
306 }
307 else if (!strcmp (cp, "off") || !strcmp (cp, "false"))
308 {
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 thawer.parse_error ("settings file");
319
320 thawer.next ();
321 }
322 }
323
324 /*
325 * init() is called only once, when starting the program.
326 */
327 void
328 init (int argc, char **argv)
329 {
330 init_done = 0; /* Must be done before init_signal() */
331
332 init_environ ();
333 cfperl_init ();
334 init_done = 1;
335 }
336
337 /* Signal handlers: */
338
339 static void
340 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 static void
349 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 rec_sigsegv (int i)
359 {
360 signal (SIGSEGV, SIG_DFL);
361
362 LOG (llevError, "SIGSEGV received.\n");
363 cleanup ("SIGSEGV received", 1);
364 }
365
366 static void
367 rec_sigbus (int i)
368 {
369 signal (SIGBUS, SIG_DFL);
370
371 LOG (llevError, "SIGBUS received\n");
372 cleanup ("SIGBUS received", 1);
373 }
374
375 static void
376 rec_sigfpe (int i)
377 {
378 signal (SIGFPE, SIG_DFL);
379
380 LOG (llevError, "SIGFPE received.\n");
381 cleanup ("SIGFPE received", 1);
382 }
383
384 void
385 reset_signals ()
386 {
387 signal (SIGABRT, SIG_DFL);
388 signal (SIGQUIT, SIG_DFL);
389 signal (SIGSEGV, SIG_DFL);
390 #ifdef SIGBUS
391 signal (SIGBUS , SIG_DFL);
392 #endif
393 signal (SIGFPE , SIG_DFL);
394 signal (SIGINT , SIG_DFL);
395 signal (SIGTERM, SIG_DFL);
396 }
397
398 void
399 init_signals ()
400 {
401 // 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 sa.sa_flags = SA_RESTART;
415
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 #ifdef SIGBUS
420 sa.sa_handler = rec_sigbus; sigaction (SIGBUS, &sa, 0);
421 #endif
422 sa.sa_handler = rec_sigfpe; sigaction (SIGFPE, &sa, 0);
423
424 sa.sa_flags |= SA_ONSTACK;
425 sa.sa_handler = rec_sigsegv; sigaction (SIGSEGV, &sa, 0);
426 }
427
428 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 /* 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 static void
488 init_races ()
489 {
490 FILE *file;
491 char race[MAX_BUF], fname[MAX_BUF], buf[MAX_BUF], *cp, variable[MAX_BUF];
492 archetype *mon = NULL;
493 static int init_done = 0;
494
495 if (init_done)
496 return;
497 init_done = 1;
498 first_race = 0;
499
500 sprintf (fname, "%s/races", settings.datadir);
501 LOG (llevDebug, "Reading races from %s...\n", fname);
502 if (!(file = fopen (fname, "r")))
503 {
504 LOG (llevError, "Cannot open races file %s: %s\n", fname, strerror (errno));
505 return;
506 }
507
508 while (fgets (buf, MAX_BUF, file) != NULL)
509 {
510 int set_race = 1, set_list = 1;
511
512 if (*buf == '#')
513 continue;
514
515 if ((cp = strchr (buf, '\n')) != NULL)
516 *cp = '\0';
517
518 cp = buf;
519 while (*cp == ' ' || *cp == '!' || *cp == '@')
520 {
521 if (*cp == '!') set_race = 0;
522 if (*cp == '@') set_list = 0;
523
524 cp++;
525 }
526
527 if (sscanf (cp, "RACE %255s", variable)) // and pray MAX_BUF is larger
528 /* set new race value */
529 strcpy (race, variable);
530 else
531 {
532 char *cp1;
533
534 /* 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
548 /* set creature race to race value */
549 if ((mon = archetype::find (cp)) == NULL)
550 LOG (llevError, "Creature %s in race file lacks archetype\n", cp);
551 else
552 {
553 if (set_race && (!mon->race || strcmp (&mon->race, race)))
554 {
555 if (mon->race)
556 LOG (llevDebug, "Resetting race to %s from %s for archetype %s\n", race, &mon->race, &mon->archname);
557
558 mon->race = race;
559 }
560
561 /* if the arch is a monster, add it to the race list */
562 if (set_list && mon->flag [FLAG_MONSTER])
563 add_to_racelist (race, mon);
564 }
565 }
566 }
567
568 fclose (file);
569 LOG (llevDebug, "done.\n");
570 }
571
572 void
573 init_beforeplay ()
574 {
575 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 }
581