1 /***********************************************************************
2  Freeciv - Copyright (C) 2004 - The Freeciv Project
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License as published by
5    the Free Software Foundation; either version 2, or (at your option)
6    any later version.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 ***********************************************************************/
13 
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
17 
18 #include <assert.h>
19 #include <stdarg.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 
24 #ifdef HAVE_SIGNAL_H
25 #include <signal.h>
26 #endif
27 
28 /* utility */
29 #include "capability.h"
30 #include "fc_cmdline.h"
31 #include "fciconv.h"
32 #include "fcintl.h"
33 #include "log.h"
34 #include "mem.h"
35 #include "registry.h"
36 #include "support.h"
37 
38 /* common */
39 #include "capstr.h"
40 #include "connection.h"
41 #include "events.h"
42 #include "fc_cmdhelp.h"
43 #include "fc_interface.h"
44 #include "fc_types.h" /* LINE_BREAK */
45 #include "game.h"
46 #include "government.h"
47 #include "improvement.h"
48 #include "map.h"
49 #include "movement.h"
50 #include "player.h"
51 #include "version.h"
52 
53 /* client */
54 #include "client_main.h"
55 #include "climisc.h"
56 #include "helpdata.h"
57 #include "helpdlg_g.h"
58 #include "tilespec.h"
59 
60 /* server */
61 #include "citytools.h"
62 #include "commands.h"
63 #include "connecthand.h"
64 #include "console.h"
65 #include "diplhand.h"
66 #include "gamehand.h"
67 #include "plrhand.h"
68 #include "report.h"
69 #include "ruleset.h"
70 #include "settings.h"
71 #include "sernet.h"
72 #include "srv_main.h"
73 #include "stdinhand.h"
74 
75 enum manuals {
76   MANUAL_SETTINGS,
77   MANUAL_COMMANDS,
78   MANUAL_TERRAIN,
79   MANUAL_BUILDINGS,
80   MANUAL_WONDERS,
81   MANUAL_GOVS,
82   MANUAL_UNITS,
83   MANUAL_COUNT
84 };
85 
86 /* This formats the manual for an HTML wiki. */
87 #ifdef MANUAL_USE_HTML
88 #define FILE_EXT "html"
89 #define HEADER "<html><head><link rel=\"stylesheet\" type=\"text/css\" "\
90                "href=\"manual.css\"/><meta http-equiv=\"Content-Type\" "\
91                "content=\"text/html; charset=UTF-8\"/></head><body>\n\n"
92 #define SECTION_BEGIN "<h3>"
93 #define SECTION_END "</h3>"
94 #define IMAGE_BEGIN "<img src=\""
95 #define IMAGE_END ".png\">"
96 #define SEPARATOR " "
97 #define TAIL "</body></html>"
98 #else  /* MANUAL_USE_HTML */
99 #define FILE_EXT "mediawiki"
100 #define HEADER " "
101 #define SECTION_BEGIN "==="
102 #define SECTION_END "==="
103 #define IMAGE_BEGIN "[[Image:"
104 #define IMAGE_END ".png]]"
105 #define SEPARATOR "----\n\n"
106 #define TAIL " "
107 #endif /* MANUAL_USE_HTML */
108 
109 void insert_client_build_info(char *outbuf, size_t outlen);
110 
111 /* Needed for "About Freeciv" help */
112 const char *client_string = "freeciv-manual";
113 
114 static char *ruleset = NULL;
115 
116 /**************************************************************************
117   Replace html special characters ('&', '<' and '>').
118 **************************************************************************/
html_special_chars(char * str,size_t * len)119 static char *html_special_chars(char *str, size_t *len)
120 {
121   char *buf;
122 
123   buf = fc_strrep_resize(str, len, "&", "&amp;");
124   buf = fc_strrep_resize(buf, len, "<", "&lt;");
125   buf = fc_strrep_resize(buf, len, ">", "&gt;");
126 
127   return buf;
128 }
129 
130 
131 /*******************************************
132   Useless stubs for compiling client code.
133 */
134 
135 /**************************************************************************
136   Client stub
137 **************************************************************************/
popup_help_dialog_string(const char * item)138 void popup_help_dialog_string(const char *item)
139 {
140   /* Empty stub. */
141 }
142 
143 /**************************************************************************
144   Client stub
145 **************************************************************************/
popdown_help_dialog(void)146 void popdown_help_dialog(void)
147 {
148   /* Empty stub. */
149 }
150 
151 struct tileset *tileset;
152 
153 /**************************************************************************
154   Client stub
155 **************************************************************************/
tileset_name_get(struct tileset * t)156 const char *tileset_name_get(struct tileset *t)
157 {
158   return NULL;
159 }
160 
161 /**************************************************************************
162   Client stub
163 **************************************************************************/
tileset_version(struct tileset * t)164 const char *tileset_version(struct tileset *t)
165 {
166   return NULL;
167 }
168 
169 /**************************************************************************
170   Client stub
171 **************************************************************************/
tileset_summary(struct tileset * t)172 const char *tileset_summary(struct tileset *t)
173 {
174   return NULL;
175 }
176 
177 /**************************************************************************
178   Client stub
179 **************************************************************************/
tileset_description(struct tileset * t)180 const char *tileset_description(struct tileset *t)
181 {
182   return NULL;
183 }
184 
185 /**************************************************************************
186   Mostly a client stub.
187 **************************************************************************/
client_state(void)188 enum client_states client_state(void)
189 {
190   return C_S_INITIAL;
191 }
192 
193 /**************************************************************************
194   Mostly a client stub.
195 **************************************************************************/
client_nation_is_in_current_set(const struct nation_type * pnation)196 bool client_nation_is_in_current_set(const struct nation_type *pnation)
197 {
198   /* Currently, there is no way to select a nation set for freeciv-manual.
199    * Then, let's assume we want to print help for all nations. */
200   return TRUE;
201 }
202 
203 /**************************************************************************
204   Write a server manual in the format chosen at build time, then quit.
205 **************************************************************************/
manual_command(void)206 static bool manual_command(void)
207 {
208   FILE *doc;
209   char filename[40];
210   enum manuals manuals;
211   struct connection my_conn;
212 
213   /* Default client access. */
214   connection_common_init(&my_conn);
215   my_conn.access_level = ALLOW_CTRL;
216 
217   /* Reset aifill to zero */
218   game.info.aifill = 0;
219 
220   if (!load_rulesets(NULL, FALSE, FALSE)) {
221     /* Failed to load correct ruleset */
222     return FALSE;
223   }
224 
225   for (manuals = 0; manuals < MANUAL_COUNT; manuals++) {
226     int i;
227     int ri;
228 
229     fc_snprintf(filename, sizeof(filename), "%s%d.%s",
230                 game.server.rulesetdir, manuals + 1, FILE_EXT);
231 
232     if (!is_reg_file_for_access(filename, TRUE)
233         || !(doc = fc_fopen(filename, "w"))) {
234       log_error(_("Could not write manual file %s."), filename);
235       return FALSE;
236     }
237 
238     fprintf(doc, HEADER);
239     fprintf(doc, "<!-- Generated by freeciv-manual version %s -->\n\n",
240             freeciv_datafile_version());
241 
242     switch (manuals) {
243     case MANUAL_SETTINGS:
244       fprintf(doc, _("<h1>Freeciv %s server options</h1>\n\n"), VERSION_STRING);
245       settings_iterate(SSET_ALL, pset) {
246         char buf[256];
247         const char *sethelp;
248 
249         fprintf(doc, SEPARATOR);
250         fprintf(doc, "%s%s - %s%s\n\n", SECTION_BEGIN, setting_name(pset),
251                 _(setting_short_help(pset)), SECTION_END);
252         sethelp = _(setting_extra_help(pset, TRUE));
253         if (strlen(sethelp) > 0) {
254           char *help = fc_strdup(sethelp);
255           size_t help_len = strlen(help) + 1;
256 
257           fc_break_lines(help, LINE_BREAK);
258           help = html_special_chars(help, &help_len);
259           fprintf(doc, "<pre>%s</pre>\n\n", help);
260           FC_FREE(help);
261         }
262         fprintf(doc, "<p class=\"misc\">");
263         fprintf(doc, _("Level: %s.<br>"),
264                 _(sset_level_name(setting_level(pset))));
265         fprintf(doc, _("Category: %s.<br>"),
266                 _(sset_category_name(setting_category(pset))));
267 
268         /* first check if the setting is locked because this is included in
269          * the function setting_is_changeable() */
270         if (setting_locked(pset)) {
271           fprintf(doc, _("Is locked by the ruleset."));
272         } else if (!setting_is_changeable(pset, &my_conn, NULL, 0)) {
273           fprintf(doc, _("Can only be used in server console."));
274         }
275 
276         fprintf(doc, "</p>\n\n");
277         setting_default_name(pset, TRUE, buf, sizeof(buf));
278         switch (setting_type(pset)) {
279         case SSET_INT:
280           fprintf(doc, "<p class=\"bounds\">%s %d, %s %s, %s %d</p>\n\n",
281                   _("Minimum:"), setting_int_min(pset),
282                   _("Default:"), buf,
283                   _("Maximum:"), setting_int_max(pset));
284           break;
285         case SSET_ENUM:
286           {
287             const char *value;
288 
289             fprintf(doc, "<p class=\"bounds\">%s</p>\n",
290                     _("Possible values:"));
291             for (i = 0; (value = setting_enum_val(pset, i, FALSE)); i++) {
292               fprintf(doc, "<p class=\"bounds\"><li/> %s: \"%s\"</p>\n",
293                       value, setting_enum_val(pset, i, TRUE));
294             }
295           }
296           break;
297         case SSET_BITWISE:
298           {
299             const char *value;
300 
301             fprintf(doc, "<p class=\"bounds\">%s</p>\n",
302                     _("Possible values (option can take any number of these):"));
303             for (i = 0; (value = setting_bitwise_bit(pset, i, FALSE)); i++) {
304               fprintf(doc, "<p class=\"bounds\"><li/> %s: \"%s\"</p>\n",
305                       value, setting_bitwise_bit(pset, i, TRUE));
306             }
307           }
308           break;
309         case SSET_BOOL:
310         case SSET_STRING:
311           break;
312         }
313         if (SSET_INT != setting_type(pset)) {
314           fprintf(doc, "<p class=\"bounds\">%s %s</p>\n\n",
315                   _("Default:"), buf);
316         }
317         if (setting_non_default(pset)) {
318           fprintf(doc, _("<p class=\"changed\">Value set to %s</p>\n\n"),
319                   setting_value_name(pset, TRUE, buf, sizeof(buf)));
320         }
321       } settings_iterate_end;
322       break;
323 
324     case MANUAL_COMMANDS:
325       fprintf(doc, _("<h1>Freeciv %s server commands</h1>\n\n"),
326               VERSION_STRING);
327       for (i = 0; i < CMD_NUM; i++) {
328         const struct command *cmd = command_by_number(i);
329 
330         fprintf(doc, SEPARATOR);
331         fprintf(doc, "%s%s  -  %s%s\n\n", SECTION_BEGIN, command_name(cmd),
332                 command_short_help(cmd), SECTION_END);
333         if (command_synopsis(cmd)) {
334           char *cmdstr = fc_strdup(command_synopsis(cmd));
335           size_t cmdstr_len = strlen(cmdstr) + 1;
336 
337           cmdstr = html_special_chars(cmdstr, &cmdstr_len);
338           fprintf(doc, _("<table>\n<tr>\n<td valign=\"top\">"
339                          "<pre>Synopsis:</pre></td>\n<td>"));
340           fprintf(doc, "<pre>%s</pre></td></tr></table>", cmdstr);
341           FC_FREE(cmdstr);
342         }
343         fprintf(doc, _("<p class=\"level\">Level: %s</p>\n\n"),
344                 cmdlevel_name(command_level(cmd)));
345         {
346           char *help = command_extra_help(cmd);
347           if (help) {
348             size_t help_len = strlen(help) + 1;
349 
350             fc_break_lines(help, LINE_BREAK);
351             help = html_special_chars(help, &help_len);
352             fprintf(doc, _("<p>Description:</p>\n\n"));
353             fprintf(doc, "<pre>%s</pre>\n\n", help);
354             FC_FREE(help);
355           }
356         }
357       }
358       break;
359 
360     case MANUAL_TERRAIN:
361       fprintf(doc, _("<h1>Freeciv %s terrain help</h1>\n\n"),
362               VERSION_STRING);
363       fprintf(doc, "<table><tr bgcolor=#9bc3d1><th colspan=2>%s</th>", _("Terrain"));
364       fprintf(doc, "<th>F/P/T</th><th>%s</th>", _("Resources"));
365       fprintf(doc, "<th>%s<br/>%s</th>", _("Move cost"), _("Defense bonus"));
366       fprintf(doc, "<th>%s<br/>%s<br/>%s<br/>%s<br/>(%s)</th>",
367               _("Irrigation"), _("Mining"), _("Transform"),
368               /* xgettext:no-c-format */
369               _("% of Road bonus"), _("turns"));
370       fprintf(doc, "<th>%s<br/>%s</th>",
371               _("Clean pollution"), _("Clean fallout"));
372       ri = 0;
373       if (game.control.num_road_types > 0) {
374         fprintf(doc, "<th>");
375       }
376       extra_type_by_cause_iterate(EC_ROAD, pextra) {
377         if (++ri < game.control.num_road_types) {
378           fprintf(doc, "%s<br/>", extra_name_translation(pextra));
379         } else {
380           /* Last one */
381           fprintf(doc, "%s</th>", extra_name_translation(pextra));
382         }
383       } extra_type_by_cause_iterate_end;
384       fprintf(doc, "</tr>\n\n");
385       terrain_type_iterate(pterrain) {
386         struct resource **r;
387 
388         if (0 == strlen(terrain_rule_name(pterrain))) {
389           /* Must be a disabled piece of terrain */
390           continue;
391         }
392 
393         fprintf(doc, "<tr><td>" IMAGE_BEGIN "%s" IMAGE_END "</td><td>%s</td>",
394                 pterrain->graphic_str, terrain_name_translation(pterrain));
395         fprintf(doc, "<td>%d/%d/%d</td>\n",
396                 pterrain->output[O_FOOD], pterrain->output[O_SHIELD],
397                 pterrain->output[O_TRADE]);
398 
399         fprintf(doc, "<td><table width=\"100%%\">\n");
400         for (r = pterrain->resources; *r; r++) {
401           fprintf(doc, "<tr><td>" IMAGE_BEGIN "%s" IMAGE_END "</td><td>%s</td>"
402                   "<td align=\"right\">%d/%d/%d</td></tr>\n",
403                   (*r)->graphic_str,
404                   resource_name_translation(*r),
405                   (*r)->output[O_FOOD],
406                   (*r)->output[O_SHIELD],
407                   (*r)->output[O_TRADE]);
408         }
409         fprintf(doc, "</table></td>\n");
410 
411         fprintf(doc, "<td align=\"center\">%d<br/>+%d%%</td>\n",
412                 pterrain->movement_cost, pterrain->defense_bonus);
413 
414         fprintf(doc, "<td><table width=\"100%%\">\n");
415         if (pterrain->irrigation_result == pterrain) {
416           fprintf(doc, "<tr><td>+%d F</td><td align=\"right\">(%d)</td></tr>\n",
417                   pterrain->irrigation_food_incr, pterrain->irrigation_time);
418         } else if (pterrain->irrigation_result == T_NONE) {
419           fprintf(doc, "<tr><td>%s</td></tr>\n", _("impossible"));
420         } else {
421           fprintf(doc, "<tr><td>%s</td><td align=\"right\">(%d)</td></tr>\n",
422                   terrain_name_translation(pterrain->irrigation_result),
423                   pterrain->irrigation_time);
424         }
425         if (pterrain->mining_result == pterrain) {
426           fprintf(doc, "<tr><td>+%d P</td><td align=\"right\">(%d)</td></tr>\n",
427                   pterrain->mining_shield_incr, pterrain->mining_time);
428         } else if (pterrain->mining_result == T_NONE) {
429           fprintf(doc, "<tr><td>%s</td></tr>\n", _("impossible"));
430         } else {
431           fprintf(doc, "<tr><td>%s</td><td align=\"right\">(%d)</td></tr>\n",
432                   terrain_name_translation(pterrain->mining_result),
433                   pterrain->mining_time);
434         }
435 
436         if (pterrain->transform_result) {
437           fprintf(doc, "<tr><td>%s</td><td align=\"right\">(%d)</td></tr>\n",
438                   terrain_name_translation(pterrain->transform_result),
439                   pterrain->transform_time);
440         } else {
441           fprintf(doc, "<tr><td>-</td><td align=\"right\">(-)</td></tr>\n");
442         }
443         fprintf(doc, "<tr><td>%d / %d / %d</td></tr>\n</table></td>\n",
444                 pterrain->road_output_incr_pct[O_FOOD],
445                 pterrain->road_output_incr_pct[O_SHIELD],
446                 pterrain->road_output_incr_pct[O_TRADE]);
447 
448         fprintf(doc, "<td align=\"center\">%d / %d</td>",
449                 pterrain->clean_pollution_time, pterrain->clean_fallout_time);
450 
451         ri = 0;
452         if (game.control.num_road_types > 0) {
453           fprintf(doc, "<td>");
454         }
455         extra_type_by_cause_iterate(EC_ROAD, pextra) {
456           if (++ri < game.control.num_road_types) {
457             fprintf(doc, "%d / ", terrain_extra_build_time(pterrain, ACTIVITY_GEN_ROAD,
458                                                            pextra));
459           } else {
460             fprintf(doc, "%d</td>", terrain_extra_build_time(pterrain, ACTIVITY_GEN_ROAD,
461                                                              pextra));
462           }
463         } extra_type_by_cause_iterate_end;
464         fprintf(doc, "</tr>\n\n");
465       } terrain_type_iterate_end;
466 
467       fprintf(doc, "</table>\n");
468 
469       break;
470 
471     case MANUAL_BUILDINGS:
472     case MANUAL_WONDERS:
473       if (manuals == MANUAL_BUILDINGS) {
474         fprintf(doc, _("<h1>Freeciv %s buildings help</h1>\n\n"), VERSION_STRING);
475       } else {
476         fprintf(doc, _("<h1>Freeciv %s wonders help</h1>\n\n"), VERSION_STRING);
477       }
478 
479       fprintf(doc, "<table>\n<tr bgcolor=#9bc3d1><th colspan=2>%s</th>"
480                    "<th>%s<br/>%s</th><th>%s<br/>%s</th><th>%s</th></tr>\n\n",
481               _("Name"), _("Cost"), _("Upkeep"),
482               _("Requirement"), _("Obsolete by"), _("More info"));
483 
484       improvement_iterate(pimprove) {
485         char buf[64000];
486         struct advance *obs_tech = NULL;
487 
488         if (!valid_improvement(pimprove)
489          || is_great_wonder(pimprove) == (manuals == MANUAL_BUILDINGS)) {
490           continue;
491         }
492 
493         helptext_building(buf, sizeof(buf), NULL, NULL, pimprove);
494 
495         fprintf(doc, "<tr><td>" IMAGE_BEGIN "%s" IMAGE_END "</td><td>%s</td>\n"
496                      "<td align=\"center\"><b>%d</b><br/>%d</td>\n<td>",
497                 pimprove->graphic_str,
498                 improvement_name_translation(pimprove),
499                 pimprove->build_cost,
500                 pimprove->upkeep);
501 
502         requirement_vector_iterate(&pimprove->reqs, req) {
503           char text[512], text2[512];
504 
505           fc_snprintf(text2, sizeof(text2),
506                       /* TRANS: improvement requires a feature to be absent. */
507                       req->present ? "%s" : _("no %s"),
508                       VUT_NONE != req->source.kind
509                       ? universal_name_translation(&req->source,
510                                                    text, sizeof(text))
511                       : Q_("?req:None"));
512           fprintf(doc, "%s<br/>", text2);
513         } requirement_vector_iterate_end;
514 
515         requirement_vector_iterate(&pimprove->obsolete_by, pobs) {
516           if (pobs->source.kind == VUT_ADVANCE && pobs->present) {
517             obs_tech = pobs->source.value.advance;
518             break;
519           }
520         } requirement_vector_iterate_end;
521 
522         fprintf(doc, "<em>%s</em></td>\n",
523                 obs_tech != NULL
524                 ? advance_name_translation(obs_tech)
525                 : Q_("?tech:None"));
526         fprintf(doc, "<td>%s</td>\n</tr>\n\n", buf);
527       } improvement_iterate_end;
528       fprintf(doc, "</table>");
529       break;
530 
531     case MANUAL_GOVS:
532       /* FIXME: this doesn't resemble the wiki manual at all. */
533       fprintf(doc, _("<h1>Freeciv %s governments help</h1>\n\n"), VERSION_STRING);
534       governments_iterate(pgov) {
535         char buf[64000];
536         fprintf(doc, "%s%s%s\n\n", SECTION_BEGIN,
537                 government_name_translation(pgov), SECTION_END);
538         helptext_government(buf, sizeof(buf), NULL, NULL, pgov);
539         fprintf(doc, "%s\n\n", buf);
540       } governments_iterate_end;
541       break;
542 
543     case MANUAL_UNITS:
544       /* FIXME: this doesn't resemble the wiki manual at all. */
545       fprintf(doc, _("<h1>Freeciv %s unit types help</h1>\n\n"),
546               VERSION_STRING);
547       unit_type_iterate(putype) {
548         char buf[64000];
549         fprintf(doc, "%s%s%s\n\n", SECTION_BEGIN,
550                 utype_name_translation(putype), SECTION_END);
551         fprintf(doc,
552                 PL_("Cost: %d shield\n",
553                     "Cost: %d shields\n",
554                     utype_build_shield_cost(putype)),
555                 utype_build_shield_cost(putype));
556         fprintf(doc, _("Upkeep: %s\n"),
557                 helptext_unit_upkeep_str(putype));
558         fprintf(doc, _("Moves: %s\n"),
559                 move_points_text(putype->move_rate, TRUE));
560         fprintf(doc, _("Vision: %d\n"),
561                 (int)sqrt((double)putype->vision_radius_sq));
562         fprintf(doc, _("Attack: %d\n"),
563                 putype->attack_strength);
564         fprintf(doc, _("Defense: %d\n"),
565                 putype->defense_strength);
566         fprintf(doc, _("Firepower: %d\n"),
567                 putype->firepower);
568         fprintf(doc, _("Hitpoints: %d\n"),
569                 putype->hp);
570         helptext_unit(buf, sizeof(buf), NULL, "", putype);
571         fprintf(doc, "%s\n\n", buf);
572       } unit_type_iterate_end;
573       break;
574 
575     case MANUAL_COUNT:
576       break;
577 
578     } /* switch */
579 
580     fprintf(doc, TAIL);
581     fclose(doc);
582     log_normal(_("Manual file %s successfully written."), filename);
583   } /* manuals */
584 
585   return TRUE;
586 }
587 
588 /**************************************************************************
589   Entry point of whole freeciv-manual program
590 **************************************************************************/
main(int argc,char ** argv)591 int main(int argc, char **argv)
592 {
593   int inx;
594   bool showhelp = FALSE;
595   bool showvers = FALSE;
596   char *option = NULL;
597   int retval = EXIT_SUCCESS;
598 
599   init_nls();
600   registry_module_init();
601   init_character_encodings(FC_DEFAULT_DATA_ENCODING, FALSE);
602 
603   /* Set the default log level. */
604   srvarg.loglevel = LOG_NORMAL;
605 
606   /* parse command-line arguments... */
607   inx = 1;
608   while (inx < argc) {
609     if ((option = get_option_malloc("--ruleset", argv, &inx, argc, TRUE))) {
610       if (ruleset != NULL) {
611         fc_fprintf(stderr, _("Multiple rulesets requested. Only one "
612                              "ruleset at a time is supported.\n"));
613       } else {
614         ruleset = option;
615       }
616     } else if (is_option("--help", argv[inx])) {
617       showhelp = TRUE;
618       break;
619     } else if (is_option("--version", argv[inx])) {
620       showvers = TRUE;
621     } else if ((option = get_option_malloc("--log", argv, &inx, argc, TRUE))) {
622       srvarg.log_filename = option;
623 #ifndef FREECIV_NDEBUG
624     } else if (is_option("--Fatal", argv[inx])) {
625       if (inx + 1 >= argc || '-' == argv[inx + 1][0]) {
626         srvarg.fatal_assertions = SIGABRT;
627       } else if (str_to_int(argv[inx + 1], &srvarg.fatal_assertions)) {
628         inx++;
629       } else {
630         fc_fprintf(stderr, _("Invalid signal number \"%s\".\n"),
631                    argv[inx + 1]);
632         inx++;
633         showhelp = TRUE;
634       }
635 #endif /* FREECIV_NDEBUG */
636     } else if ((option = get_option_malloc("--debug", argv, &inx, argc, FALSE))) {
637       if (!log_parse_level_str(option, &srvarg.loglevel)) {
638         showhelp = TRUE;
639         break;
640       }
641       free(option);
642     } else {
643       fc_fprintf(stderr, _("Unrecognized option: \"%s\"\n"), argv[inx]);
644       exit(EXIT_FAILURE);
645     }
646     inx++;
647   }
648 
649   init_our_capability();
650 
651   /* must be before con_log_init() */
652   init_connections();
653   con_log_init(srvarg.log_filename, srvarg.loglevel,
654                srvarg.fatal_assertions);
655   /* logging available after this point */
656 
657   /* Imitate a server - this is needed for as some function only work if this
658    * is set. */
659   i_am_server();
660 
661   /* Initialize game with default values */
662   game_init();
663 
664   /* Set ruleset user requested in to use */
665   if (ruleset != NULL) {
666     sz_strlcpy(game.server.rulesetdir, ruleset);
667   }
668 
669   settings_init(FALSE);
670 
671   if (showvers && !showhelp) {
672     fc_fprintf(stderr, "%s \n", freeciv_name_version());
673     exit(EXIT_SUCCESS);
674   } else if (showhelp) {
675     struct cmdhelp *help = cmdhelp_new(argv[0]);
676 
677 #ifdef DEBUG
678     cmdhelp_add(help, "d",
679                   /* TRANS: "debug" is exactly what user must type, do not translate. */
680                 _("debug NUM"),
681                 _("Set debug log level (%d to %d, or %d:file1,min,max:...)"),
682                 LOG_FATAL, LOG_DEBUG, LOG_DEBUG);
683 #else
684     cmdhelp_add(help, "d",
685                   /* TRANS: "debug" is exactly what user must type, do not translate. */
686                 _("debug NUM"),
687                 _("Set debug log level (%d to %d)"),
688                 LOG_FATAL, LOG_VERBOSE);
689 #endif /* DEBUG */
690 #ifndef FREECIV_NDEBUG
691     cmdhelp_add(help, "F",
692                   /* TRANS: "Fatal" is exactly what user must type, do not translate. */
693                 _("Fatal [SIGNAL]"),
694                 _("Raise a signal on failed assertion"));
695 #endif /* FREECIV_NDEBUG */
696     cmdhelp_add(help, "h", "help",
697                 _("Print a summary of the options"));
698     cmdhelp_add(help, "l",
699                   /* TRANS: "log" is exactly what user must type, do not translate. */
700                 _("log FILE"),
701                 _("Use FILE as logfile"));
702     cmdhelp_add(help, "r",
703                   /* TRANS: "ruleset" is exactly what user must type, do not translate. */
704                 _("ruleset RULESET"),
705                 _("Make manual for RULESET"));
706     cmdhelp_add(help, "v", "version",
707                 _("Print the version number"));
708 
709     /* The function below prints a header and footer for the options.
710      * Furthermore, the options are sorted. */
711     cmdhelp_display(help, TRUE, FALSE, TRUE);
712     cmdhelp_destroy(help);
713 
714     exit(EXIT_SUCCESS);
715   }
716 
717   if (!manual_command()) {
718     retval = EXIT_FAILURE;
719   }
720 
721   con_log_close();
722   registry_module_close();
723   free_libfreeciv();
724   free_nls();
725   cmdline_option_values_free();
726 
727   return retval;
728 }
729 
730 /**************************************************************************
731   Empty function required by helpdata
732 **************************************************************************/
insert_client_build_info(char * outbuf,size_t outlen)733 void insert_client_build_info(char *outbuf, size_t outlen)
734 {
735   /* Nothing here */
736 }
737