Atrinik Server  4.0
init.c
Go to the documentation of this file.
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * 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  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
21  * *
22  * The author can be reached at admin@atrinik.org *
23  ************************************************************************/
24 
30 #include <global.h>
31 #include <toolkit/packet.h>
32 #include <toolkit/string.h>
33 #include <faction.h>
34 #include <arch.h>
35 #include <artifact.h>
36 #include <ban.h>
37 #include <loader.h>
38 #include <player.h>
39 #include <object_methods.h>
40 #include <toolkit/clioptions.h>
41 #include <toolkit/curl.h>
42 #include <server.h>
43 #include <toolkit/socket_crypto.h>
44 #include <toolkit/path.h>
45 #include <resources.h>
46 #include <http_server.h>
47 #include <toolkit/signals.h>
48 #include <toolkit/console.h>
49 #include <toolkit/datetime.h>
50 #include <cmake.h>
51 
56 
59 
62 
64 unsigned long todtick;
65 
67 char first_map_path[MAX_BUF];
68 
71 
74 
76 #define ARCHETYPE_LEVEL_UP "level_up"
77 
78 static void init_beforeplay(void);
79 static void init_dynamic(void);
80 static void init_clocks(void);
81 
85 static void init_strings(void)
86 {
87  shstr_cons.none = add_string("none");
88  shstr_cons.NONE = add_string("NONE");
89  shstr_cons.home = add_string("- home -");
90  shstr_cons.force = add_string("force");
91  shstr_cons.portal_destination_name = add_string(PORTAL_DESTINATION_NAME);
92  shstr_cons.portal_active_name = add_string(PORTAL_ACTIVE_NAME);
93 
94  shstr_cons.player_info = add_string("player_info");
95  shstr_cons.BANK_GENERAL = add_string("BANK_GENERAL");
96  shstr_cons.of_poison = add_string("of poison");
97  shstr_cons.of_hideous_poison = add_string("of hideous poison");
98  shstr_cons.of_vile_poison = add_string("of vile poison");
99 }
100 
104 void free_strings(void)
105 {
106  int nrof_strings = sizeof(shstr_cons) / sizeof(const char *);
107  const char **ptr = (const char **) &shstr_cons;
108  int i = 0;
109 
110  for (i = 0; i < nrof_strings; i++) {
111  FREE_ONLY_HASH(ptr[i]);
112  }
113 }
114 
118 static void
120 {
121  if (settings.server_cert != NULL) {
122  efree(settings.server_cert);
123  }
124 
125  if (settings.server_cert_sig != NULL) {
126  efree(settings.server_cert_sig);
127  }
128 }
129 
130 static void console_command_shutdown(const char *params)
131 {
132  server_shutdown();
133 }
134 
135 static void
136 console_command_config (const char *params)
137 {
138  if (params == NULL) {
139  LOG(INFO,
140  "Usage: 'config <name> = <value>' to write config, "
141  "'config <name>' to read config");
142  return;
143  }
144 
145  if (strchr(params, '=') == NULL) {
146  const char *value = clioptions_get(params);
147  if (value == NULL) {
148  LOG(INFO, "No such option: %s", params);
149  } else {
150  LOG(INFO, "Configuration: %s = %s", params, value);
151  }
152  } else {
153  char *errmsg;
154  if (clioptions_load_str(params, &errmsg)) {
155  LOG(INFO, "Configuration successful.");
156  } else {
157  LOG(INFO, "Configuration failed: %s",
158  errmsg != NULL ? errmsg : "<no error message>");
159  if (errmsg != NULL) {
160  efree(errmsg);
161  }
162  }
163  }
164 }
165 
172 static void
173 console_command_active_objects (const char *params)
174 {
175  bool show_list = params != NULL && strcmp(params, "list") == 0;
176  if (show_list) {
177  LOG(INFO, "=== Active objects list ===");
178  }
179 
180  uint64_t num = 0;
181  for (object *tmp = active_objects; tmp != NULL; tmp = tmp->active_next) {
182  num++;
183  if (show_list) {
184  LOG(INFO, "%s", object_get_str(tmp));
185  }
186  }
187 
188  LOG(INFO, "Total number of active objects: %" PRIu64, num);
189 }
190 
194 void cleanup(void)
195 {
197  remove_plugins();
198  player_deinit();
199  account_deinit();
201  free_all_maps();
202  free_style_maps();
203  arch_deinit();
205  artifact_deinit();
206  free_all_images();
209  free_all_anim();
210  free_strings();
211  race_free();
212  regions_free();
214  object_deinit();
216  party_deinit();
217  free_settings();
218  toolkit_deinit();
220  free_random_map_loader();
221  free_map_header_loader();
222 }
223 
227 static const char *clioptions_option_unit_desc =
228 "Runs the unit tests. Resulting logs will be stored in 'tests/**/*.out', with "
229 "XML results in 'tests/**/*.xml'.";
231 static bool
232 clioptions_option_unit (const char *arg,
233  char **errmsg)
234 {
235  settings.unit_tests = 1;
236  return true;
237 }
238 
243 "Runs the plugin unit tests. Resulting XMLs will be stored in "
244 "'tests/unit/plugins/**/*.xml'.";
246 static bool
248  char **errmsg)
249 {
251 
252  if (arg != NULL) {
253  snprintf(VS(settings.plugin_unit_test), "%s", arg);
254  }
255 
256  return true;
257 }
258 
263 "Generates the region maps using the world maker module.\n\n"
264 "This should be done before starting up production servers.";
266 static bool
268  char **errmsg)
269 {
270  settings.world_maker = 1;
271  return true;
272 }
273 
278 "Disables the interactive console. Useful when debugging or "
279 "running the server non-interactively.";
281 static bool
283  char **errmsg)
284 {
285  settings.no_console = true;
286  return true;
287 }
288 
292 static const char *clioptions_option_version_desc =
293 "Displays the server version and exits.";
295 static bool
296 clioptions_option_version (const char *arg,
297  char **errmsg)
298 {
299  version(NULL);
300  exit(0);
301 
302  /* Not reached */
303  return true;
304 }
305 
309 static const char *clioptions_option_port_desc =
310 "Sets the port to use for server/client communication. Set to zero to disable.";
312 static bool
313 clioptions_option_port (const char *arg,
314  char **errmsg)
315 {
316  int val = atoi(arg);
317  if (val < 0 || val > UINT16_MAX) {
318  string_fmt(*errmsg,
319  "%d is an invalid port number, must be 1-%d",
320  val,
321  UINT16_MAX);
322  return false;
323  }
324 
325  settings.port = val;
326  return true;
327 }
328 
333 "Sets the port to use for crypto server/client communication. Set to zero to "
334 "disable.";
336 static bool
338  char **errmsg)
339 {
340  int val = atoi(arg);
341  if (val < 0 || val > UINT16_MAX) {
342  string_fmt(*errmsg,
343  "%d is an invalid port number, must be 1-%d",
344  val,
345  UINT16_MAX);
346  return false;
347  }
348 
349  settings.port_crypto = val;
350  return true;
351 }
352 
356 static const char *clioptions_option_libpath_desc =
357 "Where the read-only files such as the collected treasures, artifacts,"
358 "archetypes etc reside.";
360 static bool
361 clioptions_option_libpath (const char *arg,
362  char **errmsg)
363 {
364  snprintf(VS(settings.libpath), "%s", arg);
365  return true;
366 }
367 
372 "Where to read and write player data, unique maps, etc.";
374 static bool
375 clioptions_option_datapath (const char *arg,
376  char **errmsg)
377 {
378  snprintf(VS(settings.datapath), "%s", arg);
379  return true;
380 }
381 
386 "Where the maps, Python scripts, etc reside.";
388 static bool
389 clioptions_option_mapspath (const char *arg,
390  char **errmsg)
391 {
392  snprintf(VS(settings.mapspath), "%s", arg);
393  return true;
394 }
395 
400 "Where the HTTP server data files reside.\n\n"
401 "The server must have read/write access to this directory, as it will create "
402 "files inside it.";
404 static bool
405 clioptions_option_httppath (const char *arg,
406  char **errmsg)
407 {
408  snprintf(VS(settings.httppath), "%s", arg);
409  return true;
410 }
411 
416 "Where the resource data files reside.\n\n"
417 "The server must have read access to this directory.";
419 static bool
421  char **errmsg)
422 {
423  snprintf(VS(settings.resourcespath), "%s", arg);
424  return true;
425 }
426 
431 "URL of the metaserver. The server will send POST requests to this URL to "
432 "update the metaserver data.";
434 static bool
436  char **errmsg)
437 {
438  snprintf(VS(settings.metaserver_url), "%s", arg);
439  return true;
440 }
441 
446 "Hostname of the server. If set, the server will send regular updates to the "
447 "metaserver (using the URL specified with --metaserver_url).\n\n"
448 "Updates will be refused if the hostname does not resolve to the incoming IP.";
450 static bool
452  char **errmsg)
453 {
454  snprintf(VS(settings.server_host), "%s", arg);
455  return true;
456 }
457 
462 "Name of the server. This is how the server will be named in the list of "
463 "servers (the metaserver)";
465 static bool
467  char **errmsg)
468 {
469  snprintf(VS(settings.server_name), "%s", arg);
470  return true;
471 }
472 
477 "Description of the server. This should describe the server to players.";
479 static bool
481  char **errmsg)
482 {
483  snprintf(VS(settings.server_desc), "%s", arg);
484  return true;
485 }
486 
491 "Server certificate, in the format specified by ADS-7. Void unless signed by "
492 "the Atrinik staff.";
494 static bool
496  char **errmsg)
497 {
498  if (settings.server_cert != NULL) {
499  efree(settings.server_cert);
500  }
501 
502  settings.server_cert = estrdup(arg);
503  return true;
504 }
505 
510 "Signature of the server certificate, as provided by the Atrinik staff.";
512 static bool
514  char **errmsg)
515 {
516  if (settings.server_cert_sig != NULL) {
517  efree(settings.server_cert_sig);
518  }
519 
520  settings.server_cert_sig = estrdup(arg);
521  return true;
522 }
523 
528 "Adjustment to maximum magical device level the player may use.";
530 static bool
532  char **errmsg)
533 {
534  int val = atoi(arg);
535  if (val < INT8_MIN || val > INT8_MAX) {
536  string_fmt(*errmsg,
537  "Invalid value: %d; must be %d-%d",
538  val, INT8_MIN, INT8_MAX);
539  return false;
540  }
541 
543  return true;
544 }
545 
550 "Item power factor is the relation of how the player's equipped item_power "
551 "total relates to their overall level. If 1.0, then sum of the character's "
552 "equipped item's item_power can not be greater than their overall level. "
553 "If 2.0, then that sum can not exceed twice the character's overall level. "
554 "By setting this to a high enough value, you can effectively disable "
555 "the item_power code.";
557 static bool
559  char **errmsg)
560 {
561  settings.item_power_factor = atof(arg);
562  return true;
563 }
564 
569 "Whether to reload Python user modules (eg Interface.py and the like) "
570 "each time a Python script executes. If enabled, executing scripts will "
571 "be slower, but allows for easy development of modules. This should not "
572 "be enabled on production servers.";
574 static bool
576  char **errmsg)
577 {
578  if (KEYWORD_IS_TRUE(arg)) {
580  } else if (KEYWORD_IS_FALSE(arg)) {
582  } else {
583  string_fmt(*errmsg, "Invalid value: %s", arg);
584  return false;
585  }
586 
587  return true;
588 }
589 
594 "Comma-delimited list of permission groups that every player will be "
595 "able to access, eg, '[MOD],[DEV]'. 'None' is the same as not using "
596 "the option in the first place, ie, no default permission groups.";
598 static bool
600  char **errmsg)
601 {
602  if (strcmp(arg, "None") == 0) {
604  } else {
607  }
608 
609  return true;
610 }
611 
616 "Sets limits for allowed characters in account names/passwords, character "
617 "names, and their maximum length.\n\n"
618 "!!! DO NOT CHANGE FROM THE DEFAULTS UNLESS YOU ARE ABSOLUTELY SURE OF THE "
619 "CONSEQUENCES !!!\n\n"
620 "Removing characters from the sets will make players using the characters "
621 "unable to log in.\n\n"
622 "Adding special characters to account/character name limitations could pose "
623 "a security risk depending on the file-system you're using (eg, dots and "
624 "slashes or colons on Windows)."
625 "The syntax is:\n"
626 "<limit name>:<min>-<max> [characters] [characters2] ...\n\n"
627 "For example:\n"
628 "charname:4-20 [:alphaupper:] [:alphalower:] [:numeric:] [:space:] ['-]\n\n"
629 "The above sets the following rules for character names:\n"
630 " - Length must be at least four"
631 " - Length must be no more than twenty"
632 " - Characters may contain upper/lower-case letters, digits, spaces, "
633 "single-quotes and dashes.\n\n"
634 "The recognized values for the 'limit name' are: account, charname and "
635 "password\n"
636 "The special syntax allowed in the characters list expands to:\n"
637 " - :alphalower: All lower-case letters in ASCII\n"
638 " - :alphaupper: All upper-case letters in ASCII\n"
639 " - :numeric: All digits\n"
640 " - :print: All printable characters (does not include whitespace)\n"
641 " - :space: Space (you can't use a regular space in the list since spaces are "
642 "used to separate the entries)";
644 static bool
646  char **errmsg)
647 {
648  static const char *allowed_chars_names[] = {
649  "account", "charname", "password",
650  };
651  CASSERT_ARRAY(allowed_chars_names, ALLOWED_CHARS_NUM);
652 
653  char word[MAX_BUF];
654  size_t pos = 0;
655  if (!string_get_word(arg, &pos, ' ', word, sizeof(word), 0)) {
656  string_fmt(*errmsg,
657  "Invalid argument for allowed_chars option: %s",
658  arg);
659  return false;
660  }
661 
662  char *cps[2];
663  if (string_split(word, cps, arraysize(cps), ':') != arraysize(cps)) {
664  string_fmt(*errmsg,
665  "Invalid word in allowed_chars option: %s",
666  word);
667  return false;
668  }
669 
670  size_t type;
671  for (type = 0; type < ALLOWED_CHARS_NUM; type++) {
672  if (strcmp(cps[0], allowed_chars_names[type]) == 0) {
673  break;
674  }
675  }
676 
677  if (type == ALLOWED_CHARS_NUM) {
678  string_fmt(*errmsg,
679  "Invalid allowed_chars option type: %s",
680  cps[0]);
681  return false;
682  }
683 
684  int lower, upper;
685  if (sscanf(cps[1], "%d-%d", &lower, &upper) != 2) {
686  string_fmt(*errmsg,
687  "Lower/upper bounds for allowed_chars option in invalid "
688  "format: %s",
689  cps[1]);
690  return false;
691  }
692 
693  settings.limits[type][0] = lower;
694  settings.limits[type][1] = upper;
695  settings.allowed_chars[type][0] = '\0';
696 
697  while (string_get_word(arg, &pos, ' ', word, sizeof(word), 0)) {
698  if (!string_startswith(word, "[") || !string_endswith(word, "]")) {
699  continue;
700  }
701 
702  char *cmd = string_sub(word, 1, -1);
703 
704  if (string_startswith(cmd, ":") && string_endswith(cmd, ":")) {
705  char start, end;
706  if (strcmp(cmd, ":alphalower:") == 0) {
707  start = 'a';
708  end = 'z';
709  } else if (strcmp(cmd, ":alphaupper:") == 0) {
710  start = 'A';
711  end = 'Z';
712  } else if (strcmp(cmd, ":numeric:") == 0) {
713  start = '0';
714  end = '9';
715  } else if (strcmp(cmd, ":print:") == 0) {
716  start = '!';
717  end = '}';
718  } else if (strcmp(cmd, ":space:") == 0) {
719  start = end = ' ';
720  } else {
721  start = end = '\0';
722  }
723 
724  if (start != '\0' && end != '\0') {
725  char *chars = string_create_char_range(start, end);
726  snprintfcat(VS(settings.allowed_chars[type]), "%s", chars);
727  efree(chars);
728  }
729  } else {
730  snprintfcat(VS(settings.allowed_chars[type]), "%s", cmd);
731  }
732 
733  efree(cmd);
734  }
735 
736  return true;
737 }
738 
743 "Comma-separated list of IPs that are allowed to send special control-related "
744 "commands to the server.";
746 static bool
748  char **errmsg)
749 {
750  snprintf(VS(settings.control_allowed_ips), "%s", arg);
751  return true;
752 }
753 
758 "Player name that will be used to perform specific control-related operations "
759 "if none is supplied in the control commands sent to the server.\n\n"
760 "The first player is used if this option is not specified.";
762 static bool
764  char **errmsg)
765 {
766  snprintf(VS(settings.control_player), "%s", arg);
767  return true;
768 }
769 
774 "If set, will preserve temporary maps across restarts.\n\n"
775 "This effectively means the state of maps (eg, items dropped on the ground) is "
776 "preserved across server restarts.";
778 static bool
780  char **errmsg)
781 {
782  settings.recycle_tmp_maps = true;
783  return true;
784 }
785 
790 "Specifies the URL to use for data HTTP requests. The files under the "
791 "directory specified by --httppath must be reachable using this URL.\n\n"
792 "If this URL is incorrect or inaccessible from the public network, clients "
793 "will be unable to connect to the server.";
795 static bool
796 clioptions_option_http_url (const char *arg,
797  char **errmsg)
798 {
799  snprintf(VS(settings.http_url), "%s", arg);
800  return true;
801 }
802 
806 static const char *clioptions_option_speed_desc =
807 "Specifies the number of microseconds each tick lasts for, eg, a value of "
808 "125000 results in an effective server tick rate of 8 ticks per second.";
810 static bool
811 clioptions_option_speed (const char *arg,
812  char **errmsg)
813 {
814  set_max_time(atol(arg));
815  return true;
816 }
817 
822 "This command is used to increase the server processing speed, without "
823 "affecting the effective game tick-rate. This means the server will be able "
824 "to send out priority packets with slightly less delay, possibly improving "
825 "network latency.\n\n"
826 "For example, a value of two doubles the amount of processing, three triples "
827 "it and so on.";
829 static bool
831  char **errmsg)
832 {
833  set_max_time_multiplier(atoi(arg));
834  return true;
835 }
836 
841 "Selects the network stack to use. This is a comma-separated list of address "
842 "families to listen on, for example: ipv4, ipv6\n\n"
843 "It is also possible to specify IP addresses to bind to, for example: "
844 "ipv4=127.0.0.1, ipv6=::1\n\n"
845 "A value of 'dual' can be used to enable dual-stack IPv6 system with IPv4 "
846 "tunneling (this may not be supported on all systems).";
848 static bool
850  char **errmsg)
851 {
852  snprintf(VS(settings.network_stack), "%s", arg);
853  return true;
854 }
855 
860 "Enables/disables the bundled HTTP server, which is required in order to "
861 "connect to the server (by most clients). Refer to the README file for "
862 "information related to running your own HTTP server instead of the bundled "
863 "one.";
865 static bool
867  char **errmsg)
868 {
869  if (KEYWORD_IS_TRUE(arg)) {
870  settings.http_server = true;
871  } else if (KEYWORD_IS_FALSE(arg)) {
872  settings.http_server = false;
873  } else {
874  string_fmt(*errmsg, "Invalid value: %s", arg);
875  return false;
876  }
877 
878  return true;
879 }
880 
890 static void init_library(int argc, char *argv[])
891 {
892  toolkit_import(memory);
893  toolkit_import(signals);
894  signals_set_traceback_prefix(EXECUTABLE);
895 
896  toolkit_import(clioptions);
897  toolkit_import(console);
898  toolkit_import(curl);
899  toolkit_import(datetime);
900  toolkit_import(logger);
901  toolkit_import(math);
902  toolkit_import(mempool);
903  toolkit_import(packet);
904  toolkit_import(path);
905  toolkit_import(shstr);
906  toolkit_import(socket);
907  toolkit_import(socket_crypto);
908  toolkit_import(string);
909  toolkit_import(stringbuffer);
910 
911  /* Store user agent for cURL, including if this is a GNU/Linux build of
912  * the server or a Windows one. */
913  char user_agent[MAX_BUF];
914 #if defined(WIN32)
915  snprintf(VS(user_agent), "Atrinik Server (Win32)/%s (%d)",
916  PACKAGE_VERSION, SOCKET_VERSION);
917 #elif defined(__GNUC__)
918  snprintf(VS(user_agent), "Atrinik Server (GNU/Linux)/%s (%d)",
919  PACKAGE_VERSION, SOCKET_VERSION);
920 #else
921  snprintf(VS(user_agent), "Atrinik Server (Unknown)/%s (%d)",
922  PACKAGE_VERSION, SOCKET_VERSION);
923 #endif
924 
925  curl_set_user_agent(user_agent);
926 
927  /* Add console commands. */
928  console_command_add("shutdown",
929  console_command_shutdown,
930  "Shuts down the server.",
931  "Shuts down the server, saving all the data and "
932  "disconnecting all players.\n\n"
933  "All of the used memory is freed, if possible.");
934 
935  console_command_add("config",
936  console_command_config,
937  "Changes server configuration.",
938  "Configuration that is marked as changeable can be "
939  "modified with this command, and any applied "
940  "configuration can be read.");
941 
942  console_command_add("active_objects",
944  "Show the number of active objects.",
945  "Show the number of active objects in the game world. "
946  "Use 'list' to show a string representation of each "
947  "object (and where it is).");
948 
949  clioption_t *cli;
950 
951  /* Non-argument options */
952  CLIOPTIONS_CREATE(cli, unit, "Runs the unit tests");
953  CLIOPTIONS_CREATE(cli, plugin_unit, "Runs the plugin unit tests");
954  CLIOPTIONS_CREATE(cli, worldmaker, "Generates the region maps");
955  CLIOPTIONS_CREATE(cli, no_console, "Disables the interactive console");
956  CLIOPTIONS_CREATE(cli, version, "Displays the server version");
957 
958  /* Argument options */
959  CLIOPTIONS_CREATE_ARGUMENT(cli, port, "Sets the port to use");
960  CLIOPTIONS_CREATE_ARGUMENT(cli, port_crypto, "Sets the crypto port to use");
961  CLIOPTIONS_CREATE_ARGUMENT(cli, libpath, "Read-only data files location");
962  CLIOPTIONS_CREATE_ARGUMENT(cli, datapath, "Read/write data files location");
963  CLIOPTIONS_CREATE_ARGUMENT(cli, mapspath, "Map files location");
964  CLIOPTIONS_CREATE_ARGUMENT(cli, httppath, "HTTP data files location");
965  CLIOPTIONS_CREATE_ARGUMENT(cli, resourcespath, "Resource files location");
966  CLIOPTIONS_CREATE_ARGUMENT(cli, metaserver_url, "URL of the metaserver");
967  CLIOPTIONS_CREATE_ARGUMENT(cli, http_url, "URL of the HTTP server");
968  CLIOPTIONS_CREATE_ARGUMENT(cli, server_host, "Hostname of the server");
969  CLIOPTIONS_CREATE_ARGUMENT(cli, server_name, "Name of the server");
970  CLIOPTIONS_CREATE_ARGUMENT(cli, server_desc, "Description of the server");
971  CLIOPTIONS_CREATE_ARGUMENT(cli, server_cert, "Server certificate");
972  CLIOPTIONS_CREATE_ARGUMENT(cli, server_cert_sig, "Certificate signature");
973  CLIOPTIONS_CREATE_ARGUMENT(cli, allowed_chars, "Limits for accounts/names");
974 
975  /* Changeable options */
976  CLIOPTIONS_CREATE_ARGUMENT(cli, magic_devices_level, "Magic devices level");
977  clioptions_enable_changeable(cli);
978  CLIOPTIONS_CREATE_ARGUMENT(cli, item_power_factor, "Item power factor");
979  clioptions_enable_changeable(cli);
980  CLIOPTIONS_CREATE_ARGUMENT(cli,
982  "Whether to reload Python modules");
983  clioptions_enable_changeable(cli);
984  CLIOPTIONS_CREATE_ARGUMENT(cli,
986  "Permission groups applied to all players");
987  clioptions_enable_changeable(cli);
988  CLIOPTIONS_CREATE_ARGUMENT(cli,
990  "IP allowed to control the server");
991  clioptions_enable_changeable(cli);
992  CLIOPTIONS_CREATE_ARGUMENT(cli,
994  "Default player for control commands");
995  clioptions_enable_changeable(cli);
996  CLIOPTIONS_CREATE(cli,
998  "Preserve loaded map state across restarts");
999  clioptions_enable_changeable(cli);
1000  CLIOPTIONS_CREATE_ARGUMENT(cli, speed, "Server speed");
1001  clioptions_enable_changeable(cli);
1002  CLIOPTIONS_CREATE_ARGUMENT(cli, speed_multiplier, "Speed multiplier");
1003  clioptions_enable_changeable(cli);
1004  CLIOPTIONS_CREATE_ARGUMENT(cli, network_stack, "Configure network stack");
1005 
1006  CLIOPTIONS_CREATE_ARGUMENT(cli, http_server, "Enable the HTTP server");
1007 
1008  /* Import game APIs that don't need settings */
1009  toolkit_import(commands);
1010  toolkit_import(pathfinder);
1011 
1012  memset(&settings, 0, sizeof(settings));
1013 
1014  clioptions_load("server.cfg", NULL);
1015  clioptions_load("server-custom.cfg", NULL);
1016 
1017  if (argv != NULL) {
1018  clioptions_parse(argc, argv);
1019  }
1020 
1021  /* Verify the data directory is valid. */
1022  DIR *dir = opendir(settings.datapath);
1023  if (dir == NULL) {
1024  if (errno == ENOENT) {
1025 #ifdef WIN32
1026 # define STARTUP_SCRIPT "server.bat"
1027 #else
1028 # define STARTUP_SCRIPT "./server.sh"
1029 #endif
1030 
1031  LOG(ERROR,
1032  "The data directory %s does not exist.",
1033  settings.datapath);
1034  LOG(ERROR,
1035  "Please refer to the README file on the proper way of "
1036  "launching the Atrinik server, or use " STARTUP_SCRIPT " to "
1037  "launch the server.");
1038  exit(EXIT_FAILURE);
1039  } else {
1040  LOG(ERROR,
1041  "Failed to open the data directory %s: %s (%d)",
1043  strerror(errno),
1044  errno);
1045  exit(EXIT_FAILURE);
1046  }
1047 
1048 #undef STARTUP_SCRIPT
1049  }
1050 
1051  /* Check if the data directory has the correct permissions and fix them if
1052  * it doesn't. */
1053 #ifndef WIN32
1054  struct stat statbuf;
1055  if (stat(settings.datapath, &statbuf) != 0) {
1056  LOG(ERROR, "Failed to stat the data directory %s: %s (%d)",
1058  strerror(errno),
1059  errno);
1060  exit(EXIT_FAILURE);
1061  }
1062 
1063  if ((statbuf.st_mode & 0777) != SAVE_MODE_DIR) {
1064  LOG(INFO,
1065  "Data directory %s has insecure permissions (%o), setting to %o...",
1067  statbuf.st_mode & 0777,
1068  SAVE_MODE_DIR);
1069  if (chmod(settings.datapath, SAVE_MODE_DIR) != 0) {
1070  LOG(ERROR,
1071  "Failed to chmod %s, please adjust permissions "
1072  "manually: %s (%d)",
1074  strerror(errno),
1075  errno);
1076  exit(EXIT_FAILURE);
1077  }
1078  }
1079 
1080 #endif
1081 
1082  closedir(dir);
1083 
1084  curl_set_data_dir(settings.datapath);
1085  socket_crypto_set_path(settings.datapath);
1086 
1087  /* Import game APIs that need settings */
1088  toolkit_import(ban);
1089  toolkit_import(faction);
1090  toolkit_import(socket_server);
1091  toolkit_import(http_server);
1092 
1093  map_init();
1094  init_globals();
1095  objectlink_init();
1096  object_init();
1097  player_init();
1098  party_init();
1099  init_block();
1100  read_bmap_names();
1101  material_init();
1102  /* Must be after we read in the bitmaps */
1103  init_anim();
1104  /* Reads all archetypes from file */
1105  arch_init();
1106  init_dynamic();
1107  init_clocks();
1108  account_init();
1109  resources_init();
1110 }
1111 
1116 void init_globals(void)
1117 {
1118  /* Global round ticker */
1119  global_round_tag = 1;
1120 
1121  first_player = NULL;
1122  last_player = NULL;
1123  first_map = NULL;
1124  first_treasurelist = NULL;
1125  first_artifactlist = NULL;
1126  first_region = NULL;
1127  init_strings();
1128  num_animations = 0;
1129  animations = NULL;
1130  animations_allocated = 0;
1132 }
1133 
1137 static void init_dynamic(void)
1138 {
1139  archetype_t *at, *tmp;
1140  HASH_ITER(hh, arch_table, at, tmp) {
1141  if (at->clone.type == MAP && EXIT_PATH(&at->clone) != NULL) {
1142  snprintf(VS(first_map_path), "%s", EXIT_PATH(&at->clone));
1143  first_map_x = at->clone.stats.hp;
1144  first_map_y = at->clone.stats.sp;
1145  return;
1146  }
1147  }
1148 
1149  LOG(ERROR, "You need an archetype called 'map' and it has to contain "
1150  "start map.");
1151  exit(1);
1152 }
1153 
1158 void write_todclock(void)
1159 {
1160  char filename[MAX_BUF];
1161  FILE *fp;
1162 
1163  snprintf(filename, sizeof(filename), "%s/clockdata", settings.datapath);
1164 
1165  if ((fp = fopen(filename, "w")) == NULL) {
1166  LOG(BUG, "Cannot open %s for writing.", filename);
1167  return;
1168  }
1169 
1170  fprintf(fp, "%lu", todtick);
1171  fclose(fp);
1172 }
1173 
1179 static void init_clocks(void)
1180 {
1181  char filename[MAX_BUF];
1182  FILE *fp;
1183  static int has_been_done = 0;
1184 
1185  if (has_been_done) {
1186  return;
1187  } else {
1188  has_been_done = 1;
1189  }
1190 
1191  snprintf(filename, sizeof(filename), "%s/clockdata", settings.datapath);
1192 
1193  if ((fp = fopen(filename, "r")) == NULL) {
1194  LOG(DEBUG, "Can't open %s.", filename);
1195  todtick = 0;
1196  write_todclock();
1197  return;
1198  }
1199 
1200  if (fscanf(fp, "%lu", &todtick)) {
1201  }
1202 
1203  fclose(fp);
1204 }
1205 
1215 void init(int argc, char **argv)
1216 {
1217  /* We don't want to be affected by players' umask */
1218  (void) umask(0);
1219 
1220  /* Must be called early */
1221  init_library(argc, argv);
1223 
1224  /* Load up the old temp map files */
1225  read_map_log();
1226  regions_init();
1227  hiscore_init();
1228 
1229  init_beforeplay();
1231  updates_init();
1232  init_srv_files();
1233  metaserver_init();
1234  statistics_init();
1235  reset_sleep();
1236  init_plugins();
1237 }
1238 
1242 static void init_beforeplay(void)
1243 {
1244  init_spells();
1245  race_init();
1246  init_readable();
1248 }
treasure_list_t * first_treasurelist
Definition: main.c:61
static const char * clioptions_option_item_power_factor_desc
Definition: init.c:549
static const char * clioptions_option_worldmaker_desc
Definition: init.c:262
archetype_t * arch_table
Definition: arch.c:41
void init_new_exp_system(void)
Definition: skill_util.c:219
static bool clioptions_option_no_console(const char *arg, char **errmsg)
Definition: init.c:282
static bool clioptions_option_python_reload_modules(const char *arg, char **errmsg)
Definition: init.c:575
static bool clioptions_option_libpath(const char *arg, char **errmsg)
Definition: init.c:361
void init_spells(void)
Definition: spell_util.c:61
static const char * clioptions_option_speed_desc
Definition: init.c:806
void init_anim(void)
Definition: anim.c:57
void read_client_images(void)
Definition: image.c:129
void init_block(void)
Definition: los.c:63
char datapath[MAX_BUF]
Definition: global.h:343
char network_stack[MAX_BUF]
Definition: global.h:464
static bool clioptions_option_resourcespath(const char *arg, char **errmsg)
Definition: init.c:420
static bool clioptions_option_server_desc(const char *arg, char **errmsg)
Definition: init.c:480
void player_deinit(void)
Definition: player.c:68
char metaserver_url[MAX_BUF]
Definition: global.h:363
void race_init(void)
Definition: race.c:188
static bool clioptions_option_http_server(const char *arg, char **errmsg)
Definition: init.c:866
void cache_remove_all(void)
Definition: cache.c:205
uint8_t type
One of operation types.
Definition: sound_ambient.c:45
void free_object_loader(void)
Definition: object.c:48436
#define SOCKET_VERSION
Definition: config.h:181
bool unit_tests
Definition: global.h:388
void material_init(void)
Definition: material.c:62
static void init_dynamic(void)
Definition: init.c:1137
static void init_library(int argc, char *argv[])
Definition: init.c:890
static const char * clioptions_option_python_reload_modules_desc
Definition: init.c:568
void player_init(void)
Definition: player.c:58
static const char * clioptions_option_recycle_tmp_maps_desc
Definition: init.c:773
uint8_t python_reload_modules
Definition: global.h:418
static bool clioptions_option_recycle_tmp_maps(const char *arg, char **errmsg)
Definition: init.c:779
void updates_init(void)
Definition: updates.c:170
char httppath[MAX_BUF]
Definition: global.h:353
static void free_settings(void)
Definition: init.c:119
char http_url[MAX_BUF]
Definition: global.h:459
static bool clioptions_option_unit(const char *arg, char **errmsg)
Definition: init.c:232
static bool clioptions_option_speed_multiplier(const char *arg, char **errmsg)
Definition: init.c:830
void regions_free(void)
Definition: region.c:179
#define PORTAL_DESTINATION_NAME
Definition: define.h:81
bool http_server
Definition: global.h:454
char * server_cert_sig
Definition: global.h:474
void metaserver_init(void)
Definition: metaserver.c:107
region_struct * first_region
Definition: region.c:37
char default_permission_groups[MAX_BUF]
Definition: global.h:424
static bool clioptions_option_httppath(const char *arg, char **errmsg)
Definition: init.c:405
static const char * clioptions_option_magic_devices_level_desc
Definition: init.c:527
int16_t sp
Definition: living.h:78
bool plugin_unit_tests
Definition: global.h:393
static bool clioptions_option_control_player(const char *arg, char **errmsg)
Definition: init.c:763
static bool clioptions_option_worldmaker(const char *arg, char **errmsg)
Definition: init.c:267
static const char * clioptions_option_version_desc
Definition: init.c:292
static bool clioptions_option_port(const char *arg, char **errmsg)
Definition: init.c:313
static bool clioptions_option_speed(const char *arg, char **errmsg)
Definition: init.c:811
static const char * clioptions_option_server_name_desc
Definition: init.c:461
static void init_strings(void)
Definition: init.c:85
int8_t magic_devices_level
Definition: global.h:408
static bool clioptions_option_server_name(const char *arg, char **errmsg)
Definition: init.c:466
char libpath[MAX_BUF]
Definition: global.h:338
int32_t hp
Definition: living.h:72
static const char * clioptions_option_speed_multiplier_desc
Definition: init.c:821
void arch_deinit(void)
Definition: arch.c:104
void free_socket_images(void)
Definition: image.c:94
static const char * clioptions_option_server_host_desc
Definition: init.c:445
static bool clioptions_option_network_stack(const char *arg, char **errmsg)
Definition: init.c:849
int first_map_y
Definition: init.c:73
struct artifact_list * first_artifactlist
Definition: main.c:63
static bool clioptions_option_magic_devices_level(const char *arg, char **errmsg)
Definition: init.c:531
size_t limits[ALLOWED_CHARS_NUM][2]
Definition: global.h:434
void server_shutdown(void)
Definition: main.c:329
static const char * clioptions_option_allowed_chars_desc
Definition: init.c:615
static const char * clioptions_option_port_desc
Definition: init.c:309
char resourcespath[MAX_BUF]
Definition: global.h:358
void party_init(void)
Definition: party.c:64
void init(int argc, char **argv)
Definition: init.c:1215
static const char * clioptions_option_control_player_desc
Definition: init.c:757
const char * object_get_str(const object *op)
Definition: object.c:3151
static const char * clioptions_option_server_cert_sig_desc
Definition: init.c:509
void init_globals(void)
Definition: init.c:1116
Definition: arch.h:40
void resources_init(void)
Definition: resources.c:126
void init_plugins(void)
Definition: plugins.c:178
static const char * clioptions_option_mapspath_desc
Definition: init.c:385
uint16_t port_crypto
Definition: global.h:333
bool recycle_tmp_maps
Definition: global.h:449
static bool clioptions_option_metaserver_url(const char *arg, char **errmsg)
Definition: init.c:435
uint16_t port
Definition: global.h:328
void statistics_init(void)
Definition: statistics.c:50
char server_host[MAX_BUF]
Definition: global.h:368
object * active_objects
Definition: object.c:42
void free_all_anim(void)
Definition: anim.c:39
uint8_t world_maker
Definition: global.h:383
int read_bmap_names(void)
Definition: image.c:82
void artifact_deinit(void)
Definition: artifact.c:60
static const char * clioptions_option_datapath_desc
Definition: init.c:371
static bool clioptions_option_server_host(const char *arg, char **errmsg)
Definition: init.c:451
void free_all_maps(void)
Definition: map.c:1677
void read_map_log(void)
Definition: swap.c:66
void write_todclock(void)
Definition: init.c:1158
static bool clioptions_option_port_crypto(const char *arg, char **errmsg)
Definition: init.c:337
static bool clioptions_option_server_cert(const char *arg, char **errmsg)
Definition: init.c:495
static const char * clioptions_option_libpath_desc
Definition: init.c:356
char first_map_path[MAX_BUF]
Definition: init.c:67
static bool clioptions_option_version(const char *arg, char **errmsg)
Definition: init.c:296
static const char * clioptions_option_resourcespath_desc
Definition: init.c:415
static bool clioptions_option_server_cert_sig(const char *arg, char **errmsg)
Definition: init.c:513
void arch_init(void)
Definition: arch.c:78
void init_srv_files(void)
Definition: init.c:287
void cleanup(void)
Definition: init.c:194
char control_player[MAX_BUF]
Definition: global.h:444
char allowed_chars[ALLOWED_CHARS_NUM][MAX_BUF]
Definition: global.h:429
char * server_cert
Definition: global.h:469
uint64_t num
Number of successful updates.
Definition: metaserver.c:43
void party_deinit(void)
Definition: party.c:73
static const char * clioptions_option_server_desc_desc
Definition: init.c:476
static const char * clioptions_option_metaserver_url_desc
Definition: init.c:430
void init_readable(void)
Definition: readable.c:447
static const char * clioptions_option_port_crypto_desc
Definition: init.c:332
struct obj * active_next
Definition: object.h:103
void hiscore_init(void)
Definition: hiscore.c:315
char server_desc[MAX_BUF]
Definition: global.h:378
unsigned long todtick
Definition: init.c:64
static bool clioptions_option_mapspath(const char *arg, char **errmsg)
Definition: init.c:389
void regions_init(void)
Definition: region.c:47
static const char * clioptions_option_control_allowed_ips_desc
Definition: init.c:742
int world_darkness
Definition: init.c:61
char mapspath[MAX_BUF]
Definition: global.h:348
struct settings_struct settings
Definition: init.c:55
static bool clioptions_option_control_allowed_ips(const char *arg, char **errmsg)
Definition: init.c:747
void object_deinit(void)
Definition: object.c:229
static const char * clioptions_option_http_url_desc
Definition: init.c:789
static bool clioptions_option_item_power_factor(const char *arg, char **errmsg)
Definition: init.c:558
Definition: ban.c:49
void free_all_images(void)
Definition: image.c:183
void reset_sleep(void)
Definition: time.c:130
void race_free(void)
Definition: race.c:225
char server_name[MAX_BUF]
Definition: global.h:373
static const char * clioptions_option_network_stack_desc
Definition: init.c:840
static bool clioptions_option_allowed_chars(const char *arg, char **errmsg)
Definition: init.c:645
shstr_constants shstr_cons
Definition: init.c:58
living stats
Definition: object.h:481
void version(object *op)
Definition: main.c:84
void map_init(void)
Definition: map.c:148
void set_max_time(long t)
Definition: time.c:239
void init_world_darkness(void)
Definition: weather.c:43
uint8_t type
Definition: object.h:360
static void init_beforeplay(void)
Definition: init.c:1242
void free_all_readable(void)
Definition: readable.c:896
void metaserver_deinit(void)
Definition: metaserver.c:122
static void init_clocks(void)
Definition: init.c:1179
char control_allowed_ips[HUGE_BUF]
Definition: global.h:439
#define MAP
Definition: define.h:202
static const char * clioptions_option_default_permission_groups_desc
Definition: init.c:593
void free_all_treasures(void)
Definition: treasure.c:1737
void set_max_time_multiplier(int t)
Definition: time.c:259
double item_power_factor
Definition: global.h:413
static bool clioptions_option_default_permission_groups(const char *arg, char **errmsg)
Definition: init.c:599
static void console_command_active_objects(const char *params)
Definition: init.c:173
static bool clioptions_option_http_url(const char *arg, char **errmsg)
Definition: init.c:796
void object_init(void)
Definition: object.c:211
static bool clioptions_option_datapath(const char *arg, char **errmsg)
Definition: init.c:375
static const char * clioptions_option_plugin_unit_desc
Definition: init.c:242
static const char * clioptions_option_unit_desc
Definition: init.c:227
static const char * clioptions_option_http_server_desc
Definition: init.c:859
player * first_player
Definition: main.c:57
static const char * clioptions_option_httppath_desc
Definition: init.c:399
static const char * clioptions_option_no_console_desc
Definition: init.c:277
char plugin_unit_test[MAX_BUF]
Definition: global.h:403
#define FREE_ONLY_HASH(_nv_)
Definition: global.h:143
bool no_console
Definition: global.h:398
int first_map_x
Definition: init.c:70
static const char * clioptions_option_server_cert_desc
Definition: init.c:490
mapstruct * first_map
Definition: main.c:59
static bool clioptions_option_plugin_unit(const char *arg, char **errmsg)
Definition: init.c:247
player * last_player
Definition: main.c:67
void object_methods_init(void)
object clone
An object from which to do object_copy().
Definition: arch.h:47
void free_strings(void)
Definition: init.c:104
void resources_deinit(void)
Definition: resources.c:143
void remove_plugins(void)
Definition: plugins.c:345
void free_style_maps(void)
Definition: style.c:312