(svn r1154) -Add: [Network] Forked dedicated server (start openttd with -Df) (GeniusDex)
--- a/dedicated.c Sat Dec 18 13:38:27 2004 +0000
+++ b/dedicated.c Sat Dec 18 14:19:21 2004 +0000
@@ -26,8 +26,44 @@
static void *_dedicated_video_mem;
#ifdef UNIX
+/* We want to fork our dedicated server */
+void DedicatedFork()
+{
+ /* Fork the program */
+ _dedicated_pid = fork();
+ switch (_dedicated_pid) {
+ case -1:
+ perror("Unable to fork");
+ exit(1);
+ case 0:
+ // We're the child
+
+ /* Open the log-file to log all stuff too */
+ _log_file_fd = fopen(_log_file, "a");
+ if (!_log_file_fd) {
+ perror("Unable to open logfile");
+ exit(1);
+ }
+ /* Redirect stdout and stderr to log-file */
+ if (dup2(fileno(_log_file_fd), fileno(stdout)) == -1) {
+ perror("Re-routing stdout");
+ exit(1);
+ }
+ if (dup2(fileno(_log_file_fd), fileno(stderr)) == -1) {
+ perror("Re-routing stderr");
+ exit(1);
+ }
+ break;
+ default:
+ // We're the parent
+ printf("Loading dedicated server...\n");
+ printf(" - Forked to background with pid %d\n", _dedicated_pid);
+ exit(0);
+ }
+}
+
/* Signal handlers */
-void DedicatedSignalHandler(int sig)
+static void DedicatedSignalHandler(int sig)
{
_exit_game = true;
signal(sig, DedicatedSignalHandler);
@@ -57,7 +93,7 @@
#ifdef UNIX
-bool InputWaiting()
+static bool InputWaiting()
{
struct timeval tv;
fd_set readfds;
@@ -77,21 +113,48 @@
return false;
}
#else
-bool InputWaiting()
+static bool InputWaiting()
{
return kbhit();
}
#endif
-static int DedicatedVideoMainLoop() {
+static void DedicatedHandleKeyInput()
+{
+#ifdef WIN32
+ char input;
+#endif
+ char input_line[200];
+
+#ifdef UNIX
+ if (InputWaiting()) {
+ fgets(input_line, 200, stdin);
+ // Forget about the final \n (or \r)
+ strtok(input_line, "\r\n");
+ IConsoleCmdExec(input_line);
+ }
+#else
+ if (InputWaiting()) {
+ input = getch();
+ printf("%c", input);
+ if (input != '\r')
+ snprintf(input_line, 200, "%s%c", input_line, input);
+ else {
+ printf("\n");
+ IConsoleCmdExec(input_line);
+ sprintf(input_line, "");
+ }
+ }
+#endif
+}
+
+static int DedicatedVideoMainLoop()
+{
#ifndef WIN32
struct timeval tim;
-#else
- char input;
#endif
uint32 next_tick;
uint32 cur_ticks;
- char input_line[200];
#ifdef WIN32
next_tick = GetTickCount() + 30;
@@ -125,26 +188,8 @@
if (_exit_game) return ML_QUIT;
-#ifdef UNIX
- if (InputWaiting()) {
- fgets(input_line, 200, stdin);
- // Forget about the final \n (or \r)
- strtok(input_line, "\r\n");
- IConsoleCmdExec(input_line);
- }
-#else
- if (InputWaiting()) {
- input = getch();
- printf("%c", input);
- if (input != '\r')
- snprintf(input_line, 200, "%s%c", input_line, input);
- else {
- printf("\n");
- IConsoleCmdExec(input_line);
- sprintf(input_line, "");
- }
- }
-#endif
+ if (!_dedicated_forks)
+ DedicatedHandleKeyInput();
#ifdef WIN32
cur_ticks = GetTickCount();
--- a/ttd.c Sat Dec 18 13:38:27 2004 +0000
+++ b/ttd.c Sat Dec 18 14:19:21 2004 +0000
@@ -314,6 +314,7 @@
" -G seed = Set random seed\n"
" -n [ip#player:port] = Start networkgame\n"
" -D = Start dedicated server\n"
+ " -f = Fork into the background (dedicated only)\n"
" -i = Force to use the DOS palette (use this if you see a lot of pink)\n"
" -p #player = Player as #player (deprecated) (network only)\n"
);
@@ -516,6 +517,8 @@
if (_music_driver->is_song_playing()) ResetMusic();
}
+extern void DedicatedFork();
+
int ttd_main(int argc, char* argv[])
{
MyGetOptData mgo;
@@ -531,12 +534,14 @@
_game_mode = GM_MENU;
_switch_mode = SM_MENU;
_switch_mode_errorstr = INVALID_STRING_ID;
+ _dedicated_forks = false;
+ _dedicated_enabled = false;
// The last param of the following function means this:
// a letter means: it accepts that param (e.g.: -h)
// a ':' behind it means: it need a param (e.g.: -m<driver>)
// a '::' behind it means: it can optional have a param (e.g.: -d<debug>)
- MyGetOptInit(&mgo, argc-1, argv+1, "m:s:v:hDn::l:eit:d::r:g::G:p:");
+ MyGetOptInit(&mgo, argc-1, argv+1, "m:s:v:hDfn::l:eit:d::r:g::G:p:");
while ((i = MyGetOpt(&mgo)) != -1) {
switch(i) {
case 'm': ttd_strlcpy(musicdriver, mgo.opt, sizeof(musicdriver)); break;
@@ -546,7 +551,11 @@
sprintf(musicdriver,"null");
sprintf(sounddriver,"null");
sprintf(videodriver,"dedicated");
+ _dedicated_enabled = true;
} break;
+ case 'f': {
+ _dedicated_forks = true;
+ }; break;
case 'n': {
network = true;
if (mgo.opt)
@@ -595,6 +604,13 @@
}
DeterminePaths();
+
+#ifdef UNIX
+ // We must fork here, or we'll end up without some resources we need (like sockets)
+ if (_dedicated_forks)
+ DedicatedFork();
+#endif
+
LoadFromConfig();
// override config?
@@ -604,6 +620,9 @@
if (resolution[0]) { _cur_resolution[0] = resolution[0]; _cur_resolution[1] = resolution[1]; }
if (startdate != -1) _patches.starting_date = startdate;
+ if (_dedicated_forks && !_dedicated_enabled)
+ _dedicated_forks = false;
+
// enumerate language files
InitializeLanguagePacks();
--- a/unix.c Sat Dec 18 13:38:27 2004 +0000
+++ b/unix.c Sat Dec 18 14:19:21 2004 +0000
@@ -500,6 +500,7 @@
_path.gm_dir = str_fmt("%sgm/", _path.game_data_dir);
_path.data_dir = str_fmt("%sdata/", _path.game_data_dir);
_config_file = str_fmt("%sopenttd.cfg", _path.personal_dir);
+ _log_file = str_fmt("%sopenttd.log", _path.personal_dir);
#if defined CUSTOM_LANG_DIR
// sets the search path for lng files to the custom one
--- a/variables.h Sat Dec 18 13:38:27 2004 +0000
+++ b/variables.h Sat Dec 18 14:19:21 2004 +0000
@@ -322,6 +322,8 @@
VARDEF char _savegame_format[8];
VARDEF char *_config_file;
+VARDEF char *_log_file;
+VARDEF FILE *_log_file_fd;
// NOSAVE: These can be recalculated from InitializeLandscapeVariables
typedef struct {
@@ -419,6 +421,11 @@
VARDEF int _debug_ai_level;
VARDEF int _debug_net_level;
+/* Forking stuff */
+VARDEF bool _dedicated_forks;
+VARDEF bool _dedicated_enabled;
+VARDEF pid_t _dedicated_pid;
+
void CDECL debug(const char *s, ...);
#ifdef NO_DEBUG_MESSAGES
#define DEBUG(name, level)
--- a/win32.c Sat Dec 18 13:38:27 2004 +0000
+++ b/win32.c Sat Dec 18 14:19:21 2004 +0000
@@ -2061,6 +2061,7 @@
_path.lang_dir = str_fmt("%slang\\", cfg);
_config_file = str_fmt("%sopenttd.cfg", _path.personal_dir);
+ _log_file = str_fmt("%sopenttd.log", _path.personal_dir);
// make (auto)save and scenario folder
CreateDirectory(_path.save_dir, NULL);