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, "&", "&");
124 buf = fc_strrep_resize(buf, len, "<", "<");
125 buf = fc_strrep_resize(buf, len, ">", ">");
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