26#ifdef FREECIV_MSWINDOWS
30#ifdef FREECIV_HAVE_SYS_TYPES_H
69#define WAIT_BETWEEN_TRIES 100000
71#ifdef FREECIV_PATIENT_CONNECT
72#define NUMBER_OF_TRIES 10000
74#define NUMBER_OF_TRIES 500
77#if defined(HAVE_WORKING_FORK) && !defined(FREECIV_MSWINDOWS)
80#define HAVE_USABLE_FORK
83#ifdef HAVE_USABLE_FORK
84static pid_t server_pid = -1;
85#elif FREECIV_MSWINDOWS
86HANDLE server_process = INVALID_HANDLE_VALUE;
87HANDLE loghandle = INVALID_HANDLE_VALUE;
129#ifdef HAVE_USABLE_FORK
130 return (server_pid > 0);
131#elif FREECIV_MSWINDOWS
132 return (server_process != INVALID_HANDLE_VALUE);
155#ifdef HAVE_USABLE_FORK
159 if (waitpid(server_pid, NULL, WUNTRACED) <= 0) {
160 kill(server_pid, SIGTERM);
161 waitpid(server_pid, NULL, WUNTRACED);
166#elif FREECIV_MSWINDOWS
170 TerminateProcess(server_process, 0);
171 CloseHandle(server_process);
172 if (loghandle != INVALID_HANDLE_VALUE) {
173 CloseHandle(loghandle);
175 server_process = INVALID_HANDLE_VALUE;
176 loghandle = INVALID_HANDLE_VALUE;
201#ifdef HAVE_USABLE_FORK
202 kill(server_pid, SIGTERM);
203 waitpid(server_pid, NULL, WUNTRACED);
205#elif FREECIV_MSWINDOWS
206 TerminateProcess(server_process, 0);
207 CloseHandle(server_process);
208 if (loghandle != INVALID_HANDLE_VALUE) {
209 CloseHandle(loghandle);
211 server_process = INVALID_HANDLE_VALUE;
212 loghandle = INVALID_HANDLE_VALUE;
226#if !defined(HAVE_USABLE_FORK) && !defined(FREECIV_MSWINDOWS)
231 int connect_tries = 0;
237#if !defined(HAVE_USABLE_FORK)
241 PROCESS_INFORMATION pi;
254 char logcmdline[512];
255 char scriptcmdline[512];
256 char savefilecmdline[512];
257 char savescmdline[512];
258 char scenscmdline[512];
261#ifdef FREECIV_IPV6_SUPPORT
278 DEFAULT_SOCK_PORT + 1 + 10000,
279 family,
"localhost",
TRUE);
284 _(
"You'll have to start one manually. Sorry..."));
289 if (storage == NULL) {
292 _(
"You'll have to start server manually. Sorry..."));
298#ifdef HAVE_USABLE_FORK
301 const int max_nargs = 25;
302 char *argv[max_nargs + 1];
304 char dbg_lvl_buf[32];
307 bool log_to_dev_null =
FALSE;
314 argv[argc++] =
"freeciv-web";
316 argv[argc++] =
"freeciv-server";
319 argv[argc++] = port_buf;
320 argv[argc++] =
"--bind";
321 argv[argc++] =
"localhost";
325 argv[argc++] =
"--saves";
326 argv[argc++] = savesdir;
327 argv[argc++] =
"--scenarios";
328 argv[argc++] = scensdir;
330 argv[argc++] =
"none";
334 argv[argc++] =
"--debug";
336 argv[argc++] = dbg_lvl_buf;
337 argv[argc++] =
"--log";
341 argv[argc++] =
"--read";
345 argv[argc++] =
"--file";
349 argv[argc++] =
"--warnings";
352 argv[argc++] =
"--ruleset";
362 for (i = 1; i < argc; i++) {
363 astr_add(&srv_cmdline_opts, i == 1 ?
"%s" :
" %s", argv[i]);
373 if (server_pid == 0) {
383 log_to_dev_null =
TRUE;
384 fd = open(
"/dev/null", O_WRONLY);
387 fd = open(
logfile, O_WRONLY | O_CREAT | O_APPEND, 0644);
396 if (!log_to_dev_null) {
403 fd = open(
"/dev/null", O_RDONLY);
409#ifdef FREECIV_APPIMAGE
412 fc_snprintf(srvpath,
sizeof(srvpath),
"%s/usr/bin/freeciv-server",
414 execvp(srvpath, argv);
421 execvp(
"./server/freeciv-web", argv);
424 execvp(
"./freeciv-server", argv);
426 execvp(
"./fcser", argv);
427 execvp(
"./server/freeciv-server", argv);
432 execvp(BINDIR
"/freeciv-web", argv);
433 execvp(
"freeciv-web", argv);
435 execvp(BINDIR
"/freeciv-server", argv);
436 execvp(
"freeciv-server", argv);
447#ifdef FREECIV_MSWINDOWS
449 loghandle = CreateFile(
logfile, GENERIC_WRITE,
450 FILE_SHARE_READ | FILE_SHARE_WRITE,
452 OPEN_ALWAYS, 0, NULL);
455 ZeroMemory(&si,
sizeof(si));
457 si.hStdOutput = loghandle;
458 si.hStdInput = INVALID_HANDLE_VALUE;
459 si.hStdError = loghandle;
460 si.dwFlags = STARTF_USESTDHANDLES;
464 scriptcmdline[0] = 0;
465 savefilecmdline[0] = 0;
469 char *logfile_in_local_encoding =
473 fc_snprintf(logcmdline,
sizeof(logcmdline),
" --debug %s --log %s",
475 logfile_in_local_encoding);
476 free(logfile_in_local_encoding);
479 char *scriptfile_in_local_encoding =
482 fc_snprintf(scriptcmdline,
sizeof(scriptcmdline),
" --read %s",
483 scriptfile_in_local_encoding);
484 free(scriptfile_in_local_encoding);
487 char *savefile_in_local_encoding =
490 fc_snprintf(savefilecmdline,
sizeof(savefilecmdline),
" --file %s",
491 savefile_in_local_encoding);
492 free(savefile_in_local_encoding);
502 depr =
" --warnings";
513 "-p %d --bind localhost -q 1 -e%s%s%s --saves \"%s\" "
514 "--scenarios \"%s\" -A none %s%s",
516 savescmdline, scenscmdline, rsparam, depr);
520 "./server/freeciv-web %s", options);
522 fc_snprintf(cmdline1,
sizeof(cmdline1),
"./fcser %s", options);
524 "./server/freeciv-server %s", options);
529 BINDIR
"/freeciv-web %s", options);
531 "freeciv-web %s", options);
534 BINDIR
"/freeciv-server %s", options);
536 "freeciv-server %s", options);
541 !CreateProcess(NULL, cmdline1, NULL, NULL,
TRUE,
542 DETACHED_PROCESS | NORMAL_PRIORITY_CLASS,
543 NULL, NULL, &si, &pi)
545 && !CreateProcess(NULL, cmdline2, NULL, NULL,
TRUE,
546 DETACHED_PROCESS | NORMAL_PRIORITY_CLASS,
547 NULL, NULL, &si, &pi)
551 !CreateProcess(NULL, cmdline3, NULL, NULL,
TRUE,
552 DETACHED_PROCESS | NORMAL_PRIORITY_CLASS,
553 NULL, NULL, &si, &pi)
554 && !CreateProcess(NULL, cmdline4, NULL, NULL,
TRUE,
555 DETACHED_PROCESS | NORMAL_PRIORITY_CLASS,
556 NULL, NULL, &si, &pi)) {
557 log_error(
"Failed to start server process.");
559 log_verbose(
"Tried with commandline: '%s'", cmdline1);
560 log_verbose(
"Tried with commandline: '%s'", cmdline2);
562 log_verbose(
"Tried with commandline: '%s'", cmdline3);
563 log_verbose(
"Tried with commandline: '%s'", cmdline4);
566 _(
"You'll have to start one manually. Sorry..."));
570 log_verbose(
"Arguments to spawned server: %s", options);
572 server_process = pi.hProcess;
579 buf,
sizeof(buf)) == -1) {
581#ifdef HAVE_USABLE_FORK
582#ifndef FREECIV_MSWINDOWS
583 if (waitpid(server_pid, NULL, WNOHANG) != 0) {
589 log_error(
"Last error from connect attempts: '%s'", buf);
600 log_error(
"Failed to connect to spawned server!");
603 _(
"We probably couldn't start it from here."));
605 _(
"You'll have to start one manually. Sorry..."));
632 fc_strlcpy(topobuf,
"WRAPX",
sizeof(topobuf));
652 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
655 for (i = 0; i <
n - 1; i++) {
671 if (filename[0] !=
'\0') {
685 log_error(
"Couldn't create storage directory for token.");
698 log_error(
"Couldn't write token to temporary file: %s",
725 _(
"Established control over the server. "
726 "You have command access level 'hack'."));
731 _(
"Failed to obtain the required access "
732 "level to take control of the server. "
733 "Attempting to shut down server."));
768 rulesets[i][
len - suf_len] =
'\0';
void astr_free(struct astring *astr)
void astr_add(struct astring *astr, const char *format,...)
static const char * astr_str(const struct astring *astr) fc__attribute((nonnull(1)))
void attribute_flush(void)
int send_chat_printf(const char *format,...)
int send_chat(const char *message)
void output_window_append(const struct ft_color color, const char *featured_text)
int connect_to_server(const char *username, const char *hostname, int port, char *errbuf, int errbufsize)
void handle_ruleset_choices(const struct packet_ruleset_choices *packet)
void handle_single_want_hack_reply(bool you_have_hack)
void send_client_wants_hack(const char *filename)
static bool client_has_hack
void send_save_game(const char *filename)
static void randomize_string(char *str, size_t n)
#define WAIT_BETWEEN_TRIES
void set_ruleset(const char *ruleset)
bool is_server_running(void)
void client_kill_server(bool force)
bool client_start_server(void)
bool can_client_access_hack(void)
static char challenge_fullname[MAX_LEN_PATH]
bool are_deprecation_warnings_enabled(void)
char * internal_to_local_string_buffer(const char *text, char *buf, size_t bufsz)
char * internal_to_local_string_malloc(const char *text)
const struct ft_color ftc_client
void set_rulesets(int num_rulesets, char **rulesets)
const char * log_level_name(enum log_level lvl)
enum log_level log_get_level(void)
#define log_verbose(message,...)
#define fc_assert(condition)
#define log_debug(message,...)
#define log_error(message,...)
int find_next_free_port(int starting_port, int highest_port, enum fc_addr_family family, char *net_interface, bool not_avail_ok)
void desired_settable_option_update(const char *op_name, const char *op_value, bool allow_replace)
int send_packet_single_want_hack_req(struct connection *pc, const struct packet_single_want_hack_req *packet)
struct section_file * secfile_new(bool allow_duplicates)
void secfile_destroy(struct section_file *secfile)
bool secfile_save(const struct section_file *secfile, const char *filename, int compression_level, enum fz_method compression_method)
#define secfile_insert_str(secfile, string, path,...)
bool make_dir(const char *pathname)
bool is_safe_filename(const char *name)
char * freeciv_storage_dir(void)
char rulesets[MAX_NUM_RULESETS][MAX_RULESET_NAME_LENGTH]
int fc_snprintf(char *str, size_t n, const char *format,...)
size_t fc_strlcpy(char *dest, const char *src, size_t n)
void fc_usleep(unsigned long usec)
size_t fc_strlcat(char *dest, const char *src, size_t n)
int fc_remove(const char *filename)
int tileset_hex_width(const struct tileset *t)
bool tileset_is_isometric(const struct tileset *t)
int tileset_hex_height(const struct tileset *t)
char * tileset_what_ruleset(struct tileset *t)