Allow using things that were deprecated in gtk+-3.22.
[freeciv.git] / tools / civmanual.c
blobd0f33f65395d42709dad29dadf907fd03bb5625d
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.
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 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 #include <assert.h>
19 #include <stdarg.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
24 #ifdef HAVE_SIGNAL_H
25 #include <signal.h>
26 #endif
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"
38 /* common */
39 #include "connection.h"
40 #include "events.h"
41 #include "fc_cmdhelp.h"
42 #include "fc_interface.h"
43 #include "fc_types.h" /* LINE_BREAK */
44 #include "game.h"
45 #include "government.h"
46 #include "improvement.h"
47 #include "map.h"
48 #include "player.h"
49 #include "version.h"
51 /* client */
52 #include "client_main.h"
53 #include "climisc.h"
54 #include "helpdata.h"
55 #include "helpdlg_g.h"
56 #include "tilespec.h"
58 /* server */
59 #include "citytools.h"
60 #include "commands.h"
61 #include "connecthand.h"
62 #include "console.h"
63 #include "diplhand.h"
64 #include "gamehand.h"
65 #include "plrhand.h"
66 #include "report.h"
67 #include "ruleset.h"
68 #include "settings.h"
69 #include "sernet.h"
70 #include "srv_main.h"
71 #include "stdinhand.h"
73 enum manuals {
74 MANUAL_SETTINGS,
75 MANUAL_COMMANDS,
76 MANUAL_TERRAIN,
77 MANUAL_BUILDINGS,
78 MANUAL_WONDERS,
79 MANUAL_GOVS,
80 MANUAL_COUNT
83 /* This formats the manual for an HTML wiki. */
84 #ifdef MANUAL_USE_HTML
85 #define FILE_EXT "html"
86 #define HEADER "<html><head><link rel=\"stylesheet\" type=\"text/css\" "\
87 "href=\"manual.css\"/><meta http-equiv=\"Content-Type\" "\
88 "content=\"text/html; charset=UTF-8\"/></head><body>\n\n"
89 #define SECTION_BEGIN "<h3>"
90 #define SECTION_END "</h3>"
91 #define IMAGE_BEGIN "<img src=\""
92 #define IMAGE_END ".png\">"
93 #define SEPARATOR " "
94 #define TAIL "</body></html>"
95 #else /* MANUAL_USE_HTML */
96 #define FILE_EXT "mediawiki"
97 #define HEADER " "
98 #define SECTION_BEGIN "==="
99 #define SECTION_END "==="
100 #define IMAGE_BEGIN "[[Image:"
101 #define IMAGE_END ".png]]"
102 #define SEPARATOR "----\n\n"
103 #define TAIL " "
104 #endif /* MANUAL_USE_HTML */
106 void insert_client_build_info(char *outbuf, size_t outlen);
108 /* Needed for "About Freeciv" help */
109 const char *client_string = "freeciv-manual";
111 static char *ruleset = NULL;
113 /**************************************************************************
114 Replace html special characters ('&', '<' and '>').
115 **************************************************************************/
116 static char *html_special_chars(char *str, size_t *len)
118 char *buf;
120 buf = fc_strrep_resize(str, len, "&", "&amp;");
121 buf = fc_strrep_resize(buf, len, "<", "&lt;");
122 buf = fc_strrep_resize(buf, len, ">", "&gt;");
124 return buf;
128 /*******************************************
129 Useless stubs for compiling client code.
132 /**************************************************************************
133 Client stub
134 **************************************************************************/
135 void popup_help_dialog_string(const char *item)
137 /* Empty stub. */
140 /**************************************************************************
141 Client stub
142 **************************************************************************/
143 void popdown_help_dialog(void)
145 /* Empty stub. */
148 struct tileset *tileset;
150 /**************************************************************************
151 Client stub
152 **************************************************************************/
153 const char *tileset_name_get(struct tileset *t)
155 return NULL;
158 /**************************************************************************
159 Client stub
160 **************************************************************************/
161 const char *tileset_version(struct tileset *t)
163 return NULL;
166 /**************************************************************************
167 Client stub
168 **************************************************************************/
169 const char *tileset_summary(struct tileset *t)
171 return NULL;
174 /**************************************************************************
175 Client stub
176 **************************************************************************/
177 const char *tileset_description(struct tileset *t)
179 return NULL;
182 enum client_states client_state(void)
184 return C_S_INITIAL;
187 bool client_nation_is_in_current_set(const struct nation_type *pnation)
189 /* Currently, there is no way to select a nation set for freeciv-manual.
190 * Then, let's assume we want to print help for all nations. */
191 return TRUE;
194 /**************************************************************************
195 Write a server manual in the format chosen at build time, then quit.
196 **************************************************************************/
197 static bool manual_command(void)
199 FILE *doc;
200 char filename[40];
201 enum manuals manuals;
202 struct connection my_conn;
204 /* Default client access. */
205 connection_common_init(&my_conn);
206 my_conn.access_level = ALLOW_CTRL;
208 /* Reset aifill to zero */
209 game.info.aifill = 0;
211 if (!load_rulesets(NULL, FALSE, FALSE)) {
212 /* Failed to load correct ruleset */
213 return FALSE;
216 for (manuals = 0; manuals < MANUAL_COUNT; manuals++) {
217 int i;
218 int ri;
220 fc_snprintf(filename, sizeof(filename), "%s%d.%s",
221 game.server.rulesetdir, manuals + 1, FILE_EXT);
223 if (!is_reg_file_for_access(filename, TRUE)
224 || !(doc = fc_fopen(filename, "w"))) {
225 log_error(_("Could not write manual file %s."), filename);
226 return FALSE;
229 fprintf(doc, HEADER);
230 fprintf(doc, "<!-- Generated by freeciv-manual version %s -->\n\n",
231 freeciv_datafile_version());
233 switch (manuals) {
234 case MANUAL_SETTINGS:
235 fprintf(doc, _("<h1>Freeciv %s server options</h1>\n\n"), VERSION_STRING);
236 settings_iterate(SSET_ALL, pset) {
237 char buf[256];
238 const char *sethelp;
240 fprintf(doc, SEPARATOR);
241 fprintf(doc, "%s%s - %s%s\n\n", SECTION_BEGIN, setting_name(pset),
242 _(setting_short_help(pset)), SECTION_END);
243 sethelp = _(setting_extra_help(pset, TRUE));
244 if (strlen(sethelp) > 0) {
245 char *help = fc_strdup(sethelp);
246 size_t help_len = strlen(help) + 1;
248 fc_break_lines(help, LINE_BREAK);
249 help = html_special_chars(help, &help_len);
250 fprintf(doc, "<pre>%s</pre>\n\n", help);
251 FC_FREE(help);
253 fprintf(doc, "<p class=\"misc\">");
254 fprintf(doc, _("Level: %s.<br>"),
255 _(sset_level_name(setting_level(pset))));
256 fprintf(doc, _("Category: %s.<br>"),
257 _(sset_category_name(setting_category(pset))));
259 /* first check if the setting is locked because this is included in
260 * the function setting_is_changeable() */
261 if (setting_locked(pset)) {
262 fprintf(doc, _("Is locked by the ruleset."));
263 } else if (!setting_is_changeable(pset, &my_conn, NULL, 0)) {
264 fprintf(doc, _("Can only be used in server console."));
267 fprintf(doc, "</p>\n\n");
268 setting_default_name(pset, TRUE, buf, sizeof(buf));
269 switch (setting_type(pset)) {
270 case SSET_INT:
271 fprintf(doc, "<p class=\"bounds\">%s %d, %s %s, %s %d</p>\n\n",
272 _("Minimum:"), setting_int_min(pset),
273 _("Default:"), buf,
274 _("Maximum:"), setting_int_max(pset));
275 break;
276 case SSET_ENUM:
278 const char *value;
280 fprintf(doc, "<p class=\"bounds\">%s</p>\n",
281 _("Possible values:"));
282 for (i = 0; (value = setting_enum_val(pset, i, FALSE)); i++) {
283 fprintf(doc, "<p class=\"bounds\"><li/> %s: \"%s\"</p>\n",
284 value, setting_enum_val(pset, i, TRUE));
287 break;
288 case SSET_BITWISE:
290 const char *value;
292 fprintf(doc, "<p class=\"bounds\">%s</p>\n",
293 _("Possible values (option can take any number of these):"));
294 for (i = 0; (value = setting_bitwise_bit(pset, i, FALSE)); i++) {
295 fprintf(doc, "<p class=\"bounds\"><li/> %s: \"%s\"</p>\n",
296 value, setting_bitwise_bit(pset, i, TRUE));
299 break;
300 case SSET_BOOL:
301 case SSET_STRING:
302 break;
304 if (SSET_INT != setting_type(pset)) {
305 fprintf(doc, "<p class=\"bounds\">%s %s</p>\n\n",
306 _("Default:"), buf);
308 if (setting_non_default(pset)) {
309 fprintf(doc, _("<p class=\"changed\">Value set to %s</p>\n\n"),
310 setting_value_name(pset, TRUE, buf, sizeof(buf)));
312 } settings_iterate_end;
313 break;
315 case MANUAL_COMMANDS:
316 fprintf(doc, _("<h1>Freeciv %s server commands</h1>\n\n"),
317 VERSION_STRING);
318 for (i = 0; i < CMD_NUM; i++) {
319 const struct command *cmd = command_by_number(i);
321 fprintf(doc, SEPARATOR);
322 fprintf(doc, "%s%s - %s%s\n\n", SECTION_BEGIN, command_name(cmd),
323 command_short_help(cmd), SECTION_END);
324 if (command_synopsis(cmd)) {
325 char *cmdstr = fc_strdup(command_synopsis(cmd));
326 size_t cmdstr_len = strlen(cmdstr) + 1;
328 cmdstr = html_special_chars(cmdstr, &cmdstr_len);
329 fprintf(doc, _("<table>\n<tr>\n<td valign=\"top\">"
330 "<pre>Synopsis:</pre></td>\n<td>"));
331 fprintf(doc, "<pre>%s</pre></td></tr></table>", cmdstr);
332 FC_FREE(cmdstr);
334 fprintf(doc, _("<p class=\"level\">Level: %s</p>\n\n"),
335 cmdlevel_name(command_level(cmd)));
337 char *help = command_extra_help(cmd);
338 if (help) {
339 size_t help_len = strlen(help) + 1;
341 fc_break_lines(help, LINE_BREAK);
342 help = html_special_chars(help, &help_len);
343 fprintf(doc, _("<p>Description:</p>\n\n"));
344 fprintf(doc, "<pre>%s</pre>\n\n", help);
345 FC_FREE(help);
349 break;
351 case MANUAL_TERRAIN:
352 fprintf(doc, _("<h1>Freeciv %s terrain help</h1>\n\n"),
353 VERSION_STRING);
354 fprintf(doc, "<table><tr bgcolor=#9bc3d1><th colspan=2>%s</th>", _("Terrain"));
355 fprintf(doc, "<th>F/P/T</th><th>%s</th>", _("Resources"));
356 fprintf(doc, "<th>%s<br/>%s</th>", _("Move cost"), _("Defense bonus"));
357 fprintf(doc, "<th>%s<br/>%s<br/>%s<br/>%s<br/>(%s)</th>",
358 _("Irrigation"), _("Mining"), _("Transform"),
359 /* xgettext:no-c-format */
360 _("% of Road bonus"), _("turns"));
361 fprintf(doc, "<th>%s<br/>%s</th>",
362 _("Clean pollution"), _("Clean fallout"));
363 ri = 0;
364 if (game.control.num_road_types > 0) {
365 fprintf(doc, "<th>");
367 extra_type_by_cause_iterate(EC_ROAD, pextra) {
368 if (++ri < game.control.num_road_types) {
369 fprintf(doc, "%s<br/>", extra_name_translation(pextra));
370 } else {
371 /* Last one */
372 fprintf(doc, "%s</th>", extra_name_translation(pextra));
374 } extra_type_by_cause_iterate_end;
375 fprintf(doc, "</tr>\n\n");
376 terrain_type_iterate(pterrain) {
377 struct resource **r;
379 if (0 == strlen(terrain_rule_name(pterrain))) {
380 /* Must be a disabled piece of terrain */
381 continue;
384 fprintf(doc, "<tr><td>" IMAGE_BEGIN "%s" IMAGE_END "</td><td>%s</td>",
385 pterrain->graphic_str, terrain_name_translation(pterrain));
386 fprintf(doc, "<td>%d/%d/%d</td>\n",
387 pterrain->output[O_FOOD], pterrain->output[O_SHIELD],
388 pterrain->output[O_TRADE]);
390 fprintf(doc, "<td><table width=\"100%%\">\n");
391 for (r = pterrain->resources; *r; r++) {
392 fprintf(doc, "<tr><td>" IMAGE_BEGIN "%s" IMAGE_END "</td><td>%s</td>"
393 "<td align=\"right\">%d/%d/%d</td></tr>\n",
394 (*r)->graphic_str,
395 resource_name_translation(*r),
396 (*r)->output[O_FOOD],
397 (*r)->output[O_SHIELD],
398 (*r)->output[O_TRADE]);
400 fprintf(doc, "</table></td>\n");
402 fprintf(doc, "<td align=\"center\">%d<br/>+%d%%</td>\n",
403 pterrain->movement_cost, pterrain->defense_bonus);
405 fprintf(doc, "<td><table width=\"100%%\">\n");
406 if (pterrain->irrigation_result == pterrain) {
407 fprintf(doc, "<tr><td>+%d F</td><td align=\"right\">(%d)</td></tr>\n",
408 pterrain->irrigation_food_incr, pterrain->irrigation_time);
409 } else if (pterrain->irrigation_result == T_NONE) {
410 fprintf(doc, "<tr><td>%s</td></tr>\n", _("impossible"));
411 } else {
412 fprintf(doc, "<tr><td>%s</td><td align=\"right\">(%d)</td></tr>\n",
413 terrain_name_translation(pterrain->irrigation_result),
414 pterrain->irrigation_time);
416 if (pterrain->mining_result == pterrain) {
417 fprintf(doc, "<tr><td>+%d P</td><td align=\"right\">(%d)</td></tr>\n",
418 pterrain->mining_shield_incr, pterrain->mining_time);
419 } else if (pterrain->mining_result == T_NONE) {
420 fprintf(doc, "<tr><td>%s</td></tr>\n", _("impossible"));
421 } else {
422 fprintf(doc, "<tr><td>%s</td><td align=\"right\">(%d)</td></tr>\n",
423 terrain_name_translation(pterrain->mining_result),
424 pterrain->mining_time);
427 if (pterrain->transform_result) {
428 fprintf(doc, "<tr><td>%s</td><td align=\"right\">(%d)</td></tr>\n",
429 terrain_name_translation(pterrain->transform_result),
430 pterrain->transform_time);
431 } else {
432 fprintf(doc, "<tr><td>-</td><td align=\"right\">(-)</td></tr>\n");
434 fprintf(doc, "<tr><td>%d / %d / %d</td></tr>\n</table></td>\n",
435 pterrain->road_output_incr_pct[O_FOOD],
436 pterrain->road_output_incr_pct[O_SHIELD],
437 pterrain->road_output_incr_pct[O_TRADE]);
439 fprintf(doc, "<td align=\"center\">%d / %d</td>",
440 pterrain->clean_pollution_time, pterrain->clean_fallout_time);
442 ri = 0;
443 if (game.control.num_road_types > 0) {
444 fprintf(doc, "<td>");
446 extra_type_by_cause_iterate(EC_ROAD, pextra) {
447 if (++ri < game.control.num_road_types) {
448 fprintf(doc, "%d / ", terrain_extra_build_time(pterrain, ACTIVITY_GEN_ROAD,
449 pextra));
450 } else {
451 fprintf(doc, "%d</td>", terrain_extra_build_time(pterrain, ACTIVITY_GEN_ROAD,
452 pextra));
454 } extra_type_by_cause_iterate_end;
455 fprintf(doc, "</tr>\n\n");
456 } terrain_type_iterate_end;
458 fprintf(doc, "</table>\n");
460 break;
462 case MANUAL_BUILDINGS:
463 case MANUAL_WONDERS:
464 if (manuals == MANUAL_BUILDINGS) {
465 fprintf(doc, _("<h1>Freeciv %s buildings help</h1>\n\n"), VERSION_STRING);
466 } else {
467 fprintf(doc, _("<h1>Freeciv %s wonders help</h1>\n\n"), VERSION_STRING);
470 fprintf(doc, "<table>\n<tr bgcolor=#9bc3d1><th colspan=2>%s</th>"
471 "<th>%s<br/>%s</th><th>%s<br/>%s</th><th>%s</th></tr>\n\n",
472 _("Name"), _("Cost"), _("Upkeep"),
473 _("Requirement"), _("Obsolete by"), _("More info"));
475 improvement_iterate(pimprove) {
476 char buf[64000];
477 struct advance *obs_tech = NULL;
479 if (!valid_improvement(pimprove)
480 || is_great_wonder(pimprove) == (manuals == MANUAL_BUILDINGS)) {
481 continue;
484 helptext_building(buf, sizeof(buf), NULL, NULL, pimprove);
486 fprintf(doc, "<tr><td>" IMAGE_BEGIN "%s" IMAGE_END "</td><td>%s</td>\n"
487 "<td align=\"center\"><b>%d</b><br/>%d</td>\n<td>",
488 pimprove->graphic_str,
489 improvement_name_translation(pimprove),
490 pimprove->build_cost,
491 pimprove->upkeep);
493 requirement_vector_iterate(&pimprove->reqs, req) {
494 char text[512], text2[512];
495 fc_snprintf(text2, sizeof(text2),
496 /* TRANS: improvement requires a feature to be absent. */
497 req->present ? "%s" : _("no %s"),
498 VUT_NONE != req->source.kind
499 ? universal_name_translation(&req->source,
500 text, sizeof(text))
501 : Q_("?req:None"));
502 fprintf(doc, "%s<br/>", text2);
503 } requirement_vector_iterate_end;
505 requirement_vector_iterate(&pimprove->obsolete_by, pobs) {
506 if (pobs->source.kind == VUT_ADVANCE) {
507 obs_tech = pobs->source.value.advance;
508 break;
510 } requirement_vector_iterate_end;
512 fprintf(doc, "<em>%s</em></td>\n",
513 obs_tech != NULL
514 ? advance_name_translation(obs_tech)
515 : Q_("?tech:None"));
516 fprintf(doc, "<td>%s</td>\n</tr>\n\n", buf);
517 } improvement_iterate_end;
518 fprintf(doc, "</table>");
519 break;
521 case MANUAL_GOVS:
522 /* FIXME: this doesn't resemble the wiki manual at all. */
523 fprintf(doc, _("<h1>Freeciv %s governments help</h1>\n\n"), VERSION_STRING);
524 governments_iterate(pgov) {
525 char buf[64000];
526 fprintf(doc, "%s%s%s\n\n", SECTION_BEGIN,
527 government_name_translation(pgov), SECTION_END);
528 helptext_government(buf, sizeof(buf), NULL, NULL, pgov);
529 fprintf(doc, "%s\n\n", buf);
530 } governments_iterate_end;
531 break;
533 case MANUAL_COUNT:
534 break;
536 } /* switch */
538 fprintf(doc, TAIL);
539 fclose(doc);
540 log_normal(_("Manual file %s successfully written."), filename);
541 } /* manuals */
543 return TRUE;
546 /**************************************************************************
547 Entry point of whole freeciv-manual program
548 **************************************************************************/
549 int main(int argc, char **argv)
551 int inx;
552 bool showhelp = FALSE;
553 bool showvers = FALSE;
554 char *option = NULL;
555 int retval = EXIT_SUCCESS;
557 init_nls();
558 registry_module_init();
559 init_character_encodings(FC_DEFAULT_DATA_ENCODING, FALSE);
561 /* Set the default log level. */
562 srvarg.loglevel = LOG_NORMAL;
564 /* parse command-line arguments... */
565 inx = 1;
566 while (inx < argc) {
567 if ((option = get_option_malloc("--ruleset", argv, &inx, argc, TRUE))) {
568 if (ruleset != NULL) {
569 fc_fprintf(stderr, _("Multiple rulesets requested. Only one "
570 "ruleset at a time is supported.\n"));
571 } else {
572 ruleset = option;
574 } else if (is_option("--help", argv[inx])) {
575 showhelp = TRUE;
576 break;
577 } else if (is_option("--version", argv[inx])) {
578 showvers = TRUE;
579 } else if ((option = get_option_malloc("--log", argv, &inx, argc, TRUE))) {
580 srvarg.log_filename = option;
581 #ifndef FREECIV_NDEBUG
582 } else if (is_option("--Fatal", argv[inx])) {
583 if (inx + 1 >= argc || '-' == argv[inx + 1][0]) {
584 srvarg.fatal_assertions = SIGABRT;
585 } else if (str_to_int(argv[inx + 1], &srvarg.fatal_assertions)) {
586 inx++;
587 } else {
588 fc_fprintf(stderr, _("Invalid signal number \"%s\".\n"),
589 argv[inx + 1]);
590 inx++;
591 showhelp = TRUE;
593 #endif /* FREECIV_NDEBUG */
594 } else if ((option = get_option_malloc("--debug", argv, &inx, argc, FALSE))) {
595 if (!log_parse_level_str(option, &srvarg.loglevel)) {
596 showhelp = TRUE;
597 break;
599 free(option);
600 } else {
601 fc_fprintf(stderr, _("Unrecognized option: \"%s\"\n"), argv[inx]);
602 exit(EXIT_FAILURE);
604 inx++;
607 /* must be before con_log_init() */
608 init_connections();
609 con_log_init(srvarg.log_filename, srvarg.loglevel,
610 srvarg.fatal_assertions);
611 /* logging available after this point */
613 /* Imitate a server - this is needed for as some function only work if this
614 * is set. */
615 i_am_server();
617 /* Initialize game with default values */
618 game_init();
620 /* Set ruleset user requested in to use */
621 if (ruleset != NULL) {
622 sz_strlcpy(game.server.rulesetdir, ruleset);
625 settings_init(FALSE);
627 if (showvers && !showhelp) {
628 fc_fprintf(stderr, "%s \n", freeciv_name_version());
629 exit(EXIT_SUCCESS);
630 } else if (showhelp) {
631 struct cmdhelp *help = cmdhelp_new(argv[0]);
633 #ifdef DEBUG
634 cmdhelp_add(help, "d",
635 /* TRANS: "debug" is exactly what user must type, do not translate. */
636 _("debug NUM"),
637 _("Set debug log level (%d to %d, or %d:file1,min,max:...)"),
638 LOG_FATAL, LOG_DEBUG, LOG_DEBUG);
639 #else
640 cmdhelp_add(help, "d",
641 /* TRANS: "debug" is exactly what user must type, do not translate. */
642 _("debug NUM"),
643 _("Set debug log level (%d to %d)"),
644 LOG_FATAL, LOG_VERBOSE);
645 #endif /* DEBUG */
646 #ifndef FREECIV_NDEBUG
647 cmdhelp_add(help, "F",
648 /* TRANS: "Fatal" is exactly what user must type, do not translate. */
649 _("Fatal [SIGNAL]"),
650 _("Raise a signal on failed assertion"));
651 #endif /* FREECIV_NDEBUG */
652 cmdhelp_add(help, "h", "help",
653 _("Print a summary of the options"));
654 cmdhelp_add(help, "l",
655 /* TRANS: "log" is exactly what user must type, do not translate. */
656 _("log FILE"),
657 _("Use FILE as logfile"));
658 cmdhelp_add(help, "r",
659 /* TRANS: "ruleset" is exactly what user must type, do not translate. */
660 _("ruleset RULESET"),
661 _("Make manual for RULESET"));
662 cmdhelp_add(help, "v", "version",
663 _("Print the version number"));
665 /* The function below prints a header and footer for the options.
666 * Furthermore, the options are sorted. */
667 cmdhelp_display(help, TRUE, FALSE, TRUE);
668 cmdhelp_destroy(help);
670 exit(EXIT_SUCCESS);
673 if (!manual_command()) {
674 retval = EXIT_FAILURE;
677 con_log_close();
678 registry_module_close();
679 free_libfreeciv();
680 free_nls();
681 cmdline_option_values_free();
683 return retval;
686 /**************************************************************************
687 Empty function required by helpdata
688 **************************************************************************/
689 void insert_client_build_info(char *outbuf, size_t outlen)
691 /* Nothing here */