tWarnings about bad config. files / high scores now displayed graphically when graphics are available; server automatically daemonizes (if Daemonize variable is TRUE); old interactive server code removed; admin.c i18n-ised - vaccinewars - be a doctor and try to vaccinate the world
(HTM) git clone git://src.adamsgaard.dk/vaccinewars
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
(DIR) commit 47d0738498f4c81f057d5dcf14154e932399272c
(DIR) parent dda06a7bedf8d1ba29a949bee21e991fdb10243d
(HTM) Author: Ben Webb <ben@salilab.org>
Date: Mon, 19 Nov 2001 21:57:10 +0000
Warnings about bad config. files / high scores now displayed graphically
when graphics are available; server automatically daemonizes (if Daemonize
variable is TRUE); old interactive server code removed; admin.c i18n-ised
Diffstat:
M TODO | 5 +----
M config.h.in | 3 +++
M configure | 2 +-
M configure.in | 2 +-
M doc/Makefile.in | 9 ++++++---
M doc/configfile.html | 13 ++++++++-----
M src/admin.c | 10 +++++++---
M src/curses_client.c | 2 ++
M src/dopewars.c | 195 ++++++++++++++++---------------
M src/dopewars.h | 10 ++++++++--
M src/gtk_client.c | 11 +++++++----
M src/gtkport.c | 6 +++++-
M src/gtkport.h | 1 +
M src/serverside.c | 237 ++++++++++++++-----------------
M src/serverside.h | 4 +++-
M src/winmain.c | 206 ++++++++++++++++----------------
16 files changed, 359 insertions(+), 357 deletions(-)
---
(DIR) diff --git a/TODO b/TODO
t@@ -1,7 +1,4 @@
-- Admin of running servers
- DONE (- feedback when setting/querying variables)
- - mechanism for interacting with NT Service servers
-DONE for Unix - test Windows (- Fix error reporting for config. file reading)
+- Admin of running NT Service servers
- Configuration file editor thingy in the client?
- GSS_API SOCKS support?
- Fix problem with dialogs popping up while menus are open
(DIR) diff --git a/config.h.in b/config.h.in
t@@ -100,6 +100,9 @@
/* Define if you have the fgets_unlocked function. */
#undef HAVE_FGETS_UNLOCKED
+/* Define if you have the fork function. */
+#undef HAVE_FORK
+
/* Define if you have the getcwd function. */
#undef HAVE_GETCWD
(DIR) diff --git a/configure b/configure
t@@ -4260,7 +4260,7 @@ fi
fi
-for ac_func in strdup strstr getopt_long
+for ac_func in strdup strstr getopt_long fork
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:4267: checking for $ac_func" >&5
(DIR) diff --git a/configure.in b/configure.in
t@@ -175,7 +175,7 @@ dnl Checks for library functions.
AC_FUNC_MEMCMP
AC_FUNC_SETVBUF_REVERSED
AC_FUNC_STRFTIME
-AC_CHECK_FUNCS(strdup strstr getopt_long)
+AC_CHECK_FUNCS(strdup strstr getopt_long fork)
dnl Enable networking by default under Win32, but on Unix systems
dnl make it dependent on the availability of select and socket
(DIR) diff --git a/doc/Makefile.in b/doc/Makefile.in
t@@ -1,6 +1,6 @@
-# Makefile.in generated automatically by automake 1.4 from Makefile.am
+# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
t@@ -96,7 +96,10 @@ WNDRES = @WNDRES@
localedir = @localedir@
DOCPATH = ${DESTDIR}${datadir}/doc/${PACKAGE}-${VERSION}/
-DOCS = aiplayer.html configfile.html index.html i18n.html server.html clientplay.html credits.html installation.html servercommands.html commandline.html developer.html metaserver.html protocol.html windows.html
+DOCS = aiplayer.html configfile.html index.html i18n.html server.html \
+ clientplay.html credits.html installation.html \
+ servercommands.html commandline.html developer.html \
+ metaserver.html protocol.html windows.html
man_MANS = dopewars.6
EXTRA_DIST = ${man_MANS}
(DIR) diff --git a/doc/configfile.html b/doc/configfile.html
t@@ -148,13 +148,16 @@ vanishes completely. Clicking on the System Tray icon will restore the
window to its normal state. If FALSE, the System Tray is not used. Only
supported on Windows systems.</dd>
-<dt><b>Pager=<i>"more"</i></b></dt>
-<dd>Sets the pager used to display multi-page output in an interactive server
-to <i>more</i>. ("less" is a popular alternative)</dd>
+<dt><b>Daemonize=<i>TRUE</i></b></dt>
+<dd>When the Unix server is successfully started, it immediately uses the
+fork() function to become a daemon, running in the background. Since this
+can cause problems with debugging, or with other programs that need to keep
+track of the process, setting Daemonize to FALSE will run the program in the
+foreground. Only supported on Unix systems.</dd>
<dt><b>ConfigVerbose=<i>FALSE</i></b></dt>
<dd>Prints extra feedback information when processing the config. file if set
-to TRUE; this only takes affect, of course, after the ConfigVerbose variable is
+to TRUE; this only takes effect, of course, after the ConfigVerbose variable is
set, and then remains in force until it is reset again.</dd>
</dl>
t@@ -604,6 +607,6 @@ any drugs, and clients will display this information if available.</dd>
<ul>
<li><a href="index.html">Main index</a></li>
</ul>
-<p>Last update: <b>20-11-2001</b></p>
+<p>Last update: <b>18-11-2001</b></p>
</body>
</html>
(DIR) diff --git a/src/admin.c b/src/admin.c
t@@ -26,11 +26,15 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
#include <errno.h>
#include <stdio.h>
#include <glib.h>
#include "network.h"
+#include "nls.h"
#include "serverside.h"
static int OpenSocket(void) {
t@@ -40,8 +44,8 @@ static int OpenSocket(void) {
sockname=GetLocalSocket();
- g_print("Attempting to connect to local dopewars server via. Unix domain\n"
- "socket %s...\n",sockname);
+ g_print(_("Attempting to connect to local dopewars server via. Unix domain\n"
+ "socket %s...\n"),sockname);
sock = socket(PF_UNIX,SOCK_STREAM,0);
if (sock==-1) { perror("socket"); exit(1); }
t@@ -53,7 +57,7 @@ static int OpenSocket(void) {
perror("connect"); exit(1);
}
- g_print("Connection established.\n\n");
+ g_print(_("Connection established; use Ctrl-D to close your session.\n\n"));
g_free(sockname);
return sock;
(DIR) diff --git a/src/curses_client.c b/src/curses_client.c
t@@ -2031,6 +2031,8 @@ void CursesLoop(void) {
char c;
Player *Play;
+ if (!CheckHighScoreFileConfig()) return;
+
start_curses();
Width=COLS; Depth=LINES;
(DIR) diff --git a/src/dopewars.c b/src/dopewars.c
t@@ -52,10 +52,8 @@
#include "AIPlayer.h"
#ifdef GUI_SERVER
-#ifndef CYGWIN
#include "gtkport.h"
#endif
-#endif
int ClientSock,ListenSock;
gboolean Network,Client,Server,NotifyMetaServer,AIPlayer;
t@@ -66,17 +64,20 @@ gboolean Network,Client,Server,NotifyMetaServer,AIPlayer;
dopewars in single-player or antique mode:
Network=Server=Client=FALSE
*/
-FILE *logfp;
unsigned Port=7902;
gboolean Sanitized,ConfigVerbose,DrugValue;
-gchar *HiScoreFile=NULL,*ServerName=NULL,*Pager=NULL,*ConvertFile=NULL;
+gchar *HiScoreFile=NULL,*ServerName=NULL,*ConvertFile=NULL;
gboolean WantHelp,WantVersion,WantAntique,WantColour,WantNetwork,
WantConvert,WantAdmin;
#ifdef CYGWIN
gboolean MinToSysTray=TRUE;
+#else
+gboolean Daemonize=TRUE;
#endif
+gint ConfigErrors=0;
+
ClientType WantedClient;
int NumLocation=0,NumGun=0,NumCop=0,NumDrug=0,NumSubway=0,
NumPlaying=0,NumStoppedTo=0;
t@@ -271,9 +272,11 @@ struct GLOBALS Globals[] = {
{ NULL,&MinToSysTray,NULL,NULL,NULL,"MinToSysTray",
N_("If TRUE, the server minimizes to the System Tray"),
NULL,NULL,0,"",NULL,NULL },
+#else
+ { NULL,&Daemonize,NULL,NULL,NULL,"Daemonize",
+ N_("If TRUE, the server runs in the background"),
+ NULL,NULL,0,"",NULL,NULL },
#endif
- { NULL,NULL,NULL,&Pager,NULL,"Pager",
- N_("Program used to display multi-page output"),NULL,NULL,0,"",NULL,NULL },
{ &NumTurns,NULL,NULL,NULL,NULL,"NumTurns",
N_("No. of game turns (if 0, game never ends)"),
NULL,NULL,0,"",NULL,NULL },
t@@ -1425,48 +1428,34 @@ void ScannerErrorHandler(GScanner *scanner,gchar *msg,gint error) {
void ReadConfigFile(char *FileName) {
/* Read a configuration file given by "FileName"; GScanner under Win32 */
/* doesn't work properly with files, so we use a nasty workaround */
- FILE *fp;
- gint errors=0;
+ FILE *fp;
#ifdef CYGWIN
- char *buf;
+ char *buf;
#endif
- GScanner *scanner;
- fp=fopen(FileName,"r");
- if (fp) {
- scanner=g_scanner_new(&ScannerConfig);
- scanner->input_name=FileName;
- scanner->msg_handler=ScannerErrorHandler;
+ GScanner *scanner;
+ fp=fopen(FileName,"r");
+ if (fp) {
+ scanner=g_scanner_new(&ScannerConfig);
+ scanner->input_name=FileName;
+ scanner->msg_handler=ScannerErrorHandler;
#ifdef CYGWIN
- read_string(fp,&buf); if (!buf) { fclose(fp); return; }
- g_scanner_input_text(scanner,buf,strlen(buf));
+ read_string(fp,&buf); if (!buf) { fclose(fp); return; }
+ g_scanner_input_text(scanner,buf,strlen(buf));
#else
- g_scanner_input_file(scanner,fileno(fp));
-#endif
- while (!g_scanner_eof(scanner)) if (!ParseNextConfig(scanner,FALSE)) {
- errors++;
- g_scanner_error(scanner,
- _("Unable to process configuration file line %d"),
- g_scanner_cur_line(scanner));
- }
- g_scanner_destroy(scanner);
- fclose(fp);
-#ifdef CYGWIN
- g_free(buf);
+ g_scanner_input_file(scanner,fileno(fp));
#endif
- if (errors) {
+ while (!g_scanner_eof(scanner)) if (!ParseNextConfig(scanner,FALSE)) {
+ ConfigErrors++;
+ g_scanner_error(scanner,
+ _("Unable to process configuration file %s, line %d"),
+ FileName,g_scanner_cur_line(scanner));
+ }
+ g_scanner_destroy(scanner);
+ fclose(fp);
#ifdef CYGWIN
- g_warning(
-_("Errors were encountered during the reading of the configuration file.\n"
-"As as result, some settings may not work as expected. Please consult the\n"
-"file \"dopewars-log.txt\" for further details."));
-#else
- g_warning(
-_("Errors were encountered during the reading of the configuration\n"
-"file. As a result, some settings may not work as expected. Please see the\n"
-"messages on standard output for further details."));
+ g_free(buf);
#endif
- }
- }
+ }
}
gboolean ParseNextConfig(GScanner *scanner,gboolean print) {
t@@ -1788,7 +1777,7 @@ gboolean SetConfigValue(int GlobalIndex,int StructIndex,gboolean IndexGiven,
return TRUE;
}
-void SetupParameters() {
+void SetupParameters(void) {
/* Sets up data - such as the location of the high score file - to */
/* hard-coded internal values, and then processes the global and */
/* user-specific configuration files */
t@@ -1815,16 +1804,15 @@ void SetupParameters() {
Log.Level=2;
Log.Timestamp=g_strdup("[%H:%M:%S] ");
- Log.File=NULL;
+ Log.File=g_strdup("");
Currency.Symbol = g_strdup("$");
Currency.Prefix = TRUE;
/* Set hard-coded default values */
- g_free(HiScoreFile); g_free(ServerName); g_free(Pager);
+ g_free(HiScoreFile); g_free(ServerName);
HiScoreFile=g_strdup_printf("%s/dopewars.sco",DATADIR);
ServerName=g_strdup("localhost");
- Pager=g_strdup("more");
CopyNames(&Names,&DefaultNames);
CopyDrugs(&Drugs,&DefaultDrugs);
t@@ -2019,15 +2007,19 @@ void HandleCmdLine(int argc,char *argv[]) {
} while (c!=-1);
}
-int GeneralStartup(int argc,char *argv[]) {
-/* Does general startup stuff (config. files, command line, and high */
-/* score init.) - Returns 0 if OK, -1 if something failed. */
- SetupParameters();
- HandleCmdLine(argc,argv);
- if (!WantVersion && !WantHelp && !AIPlayer && !WantConvert && !WantAdmin) {
- return InitHighScoreFile();
- }
- return 0;
+void GeneralStartup(int argc,char *argv[]) {
+/* Does general startup stuff (config. files, command line, and high
+ score init.) */
+
+ ConfigErrors=0;
+ SetupParameters();
+ HandleCmdLine(argc,argv);
+
+ if (!WantVersion && !WantHelp && !AIPlayer && !WantConvert && !WantAdmin) {
+ OpenHighScoreFile();
+ } else {
+ DropPrivileges();
+ }
}
GString *GetLogString(GLogLevelFlags log_level,const gchar *message) {
t@@ -2055,6 +2047,24 @@ GString *GetLogString(GLogLevelFlags log_level,const gchar *message) {
return text;
}
+void OpenLog(void) {
+ CloseLog();
+ if (Log.File[0]=='\0') return;
+ Log.fp = fopen(Log.File,"a");
+ if (Log.fp) {
+#ifdef SETVBUF_REVERSED /* 2nd and 3rd arguments are reversed on some systems */
+ setvbuf(Log.fp,_IOLBF,(char *)NULL,0);
+#else
+ setvbuf(Log.fp,(char *)NULL,_IOLBF,0);
+#endif
+ }
+}
+
+void CloseLog(void) {
+ if (Log.fp) fclose(Log.fp);
+ Log.fp = NULL;
+}
+
#ifndef CYGWIN
#if NETWORKING && !GUI_SERVER
t@@ -2063,7 +2073,7 @@ static void ServerLogMessage(const gchar *log_domain,GLogLevelFlags log_level,
GString *text;
text=GetLogString(log_level,message);
if (text) {
- fprintf(logfp ? logfp : stdout,"%s\n",text->str);
+ fprintf(Log.fp ? Log.fp : stdout,"%s\n",text->str);
g_string_free(text,TRUE);
}
}
t@@ -2076,59 +2086,50 @@ int main(int argc,char *argv[]) {
bindtextdomain(PACKAGE,LOCALEDIR);
textdomain(PACKAGE);
#endif
- if (GeneralStartup(argc,argv)==0) {
- if (WantVersion || WantHelp) {
- HandleHelpTexts();
- } else if (WantAdmin) {
- AdminServer();
- } else if (WantConvert) {
- ConvertHighScoreFile();
- } else {
+ GeneralStartup(argc,argv);
+ OpenLog();
+ if (WantVersion || WantHelp) {
+ HandleHelpTexts();
+ } else if (WantAdmin) {
+ AdminServer();
+ } else if (WantConvert) {
+ ConvertHighScoreFile();
+ } else {
#ifdef NETWORKING
- StartNetworking();
+ StartNetworking();
#endif
- if (Server) {
+ if (Server) {
#ifdef NETWORKING
#ifdef GUI_SERVER
- gtk_set_locale();
- gtk_init(&argc,&argv);
- GuiServerLoop(FALSE);
-#else
-/* Deal with dopelog() stuff nicely */
- logfp = fopen(Log.File,"a");
- if (logfp) {
-#ifdef SETVBUF_REVERSED /* 2nd and 3rd arguments are reversed on some systems */
- setvbuf(logfp,_IOLBF,(char *)NULL,0);
+ gtk_set_locale();
+ gtk_init(&argc,&argv);
+ GuiServerLoop(FALSE);
#else
- setvbuf(logfp,(char *)NULL,_IOLBF,0);
-#endif
- }
- g_log_set_handler(NULL,LogMask(),ServerLogMessage,NULL);
- /*if (fork()<=0)*/ ServerLoop();
- if (logfp) fclose(logfp);
+ g_log_set_handler(NULL,LogMask(),ServerLogMessage,NULL);
+ ServerLoop();
#endif /* GUI_SERVER */
#else
- g_print(_("This binary has been compiled without networking "
- "support, and thus cannot run\nin server mode. "
- "Recompile passing --enable-networking to the "
- "configure script.\n"));
+ g_print(_("This binary has been compiled without networking "
+ "support, and thus cannot run\nin server mode. "
+ "Recompile passing --enable-networking to the "
+ "configure script.\n"));
#endif /* NETWORKING */
- } else if (AIPlayer) {
- AIPlayerLoop();
- } else switch(WantedClient) {
- case CLIENT_AUTO:
- if (!GtkLoop(&argc,&argv,TRUE)) CursesLoop();
- break;
- case CLIENT_WINDOW:
- GtkLoop(&argc,&argv,FALSE); break;
- case CLIENT_CURSES:
- CursesLoop(); break;
- }
+ } else if (AIPlayer) {
+ AIPlayerLoop();
+ } else switch(WantedClient) {
+ case CLIENT_AUTO:
+ if (!GtkLoop(&argc,&argv,TRUE)) CursesLoop();
+ break;
+ case CLIENT_WINDOW:
+ GtkLoop(&argc,&argv,FALSE); break;
+ case CLIENT_CURSES:
+ CursesLoop(); break;
+ }
#ifdef NETWORKING
- StopNetworking();
+ StopNetworking();
#endif
- }
}
+ CloseLog();
CloseHighScoreFile();
g_free(PidFile);
g_free(Log.File);
(DIR) diff --git a/src/dopewars.h b/src/dopewars.h
t@@ -145,6 +145,7 @@ struct LOG {
gchar *File;
gint Level;
gchar *Timestamp;
+ FILE *fp;
};
t@@ -153,11 +154,13 @@ extern gboolean Network,Client,Server,NotifyMetaServer,AIPlayer;
extern unsigned Port;
extern gboolean Sanitized,ConfigVerbose,DrugValue;
extern int NumLocation,NumGun,NumCop,NumDrug,NumSubway,NumPlaying,NumStoppedTo;
-extern gchar *HiScoreFile,*ServerName,*Pager,*ConvertFile;
+extern gchar *HiScoreFile,*ServerName,*ConvertFile;
extern gboolean WantHelp,WantVersion,WantAntique,WantColour,
WantNetwork,WantConvert,WantAdmin;
#ifdef CYGWIN
extern gboolean MinToSysTray;
+#else
+extern gboolean Daemonize;
#endif
extern ClientType WantedClient;
extern int LoanSharkLoc,BankLoc,GunShopLoc,RoughPubLoc;
t@@ -326,6 +329,7 @@ extern char **StoppedTo;
extern GSList *ServerList;
extern GScannerConfig ScannerConfig;
extern struct LOG Log;
+extern gint ConfigErrors;
GSList *RemovePlayer(Player *Play,GSList *First);
Player *GetPlayerByID(guint ID,GSList *First);
t@@ -382,7 +386,7 @@ void SetPlayerName(Player *Play,char *Name);
void HandleCmdLine(int argc,char *argv[]);
void SetupParameters(void);
void HandleHelpTexts(void);
-int GeneralStartup(int argc,char *argv[]);
+void GeneralStartup(int argc,char *argv[]);
void ReadConfigFile(char *FileName);
gboolean ParseNextConfig(GScanner *scanner,gboolean print);
int GetGlobalIndex(gchar *ID1,gchar *ID2);
t@@ -397,4 +401,6 @@ GLogLevelFlags LogMask(void);
GString *GetLogString(GLogLevelFlags log_level,const gchar *message);
void RestoreConfig(void);
void ScannerErrorHandler(GScanner *scanner,gchar *msg,gint error);
+void OpenLog(void);
+void CloseLog(void);
#endif
(DIR) diff --git a/src/gtk_client.c b/src/gtk_client.c
t@@ -193,8 +193,9 @@ static void LogMessage(const gchar *log_domain,GLogLevelFlags log_level,
const gchar *message,gpointer user_data) {
GtkMessageBox(NULL,message,
/* Titles of the message boxes for warnings and errors */
- log_level&G_LOG_LEVEL_WARNING ? _("Warning") : _("Message"),
- MB_OK|MB_IMMRETURN);
+ log_level&G_LOG_LEVEL_WARNING ? _("Warning") :
+ log_level&G_LOG_LEVEL_CRITICAL ? _("Error") : _("Message"),
+ MB_OK|(gtk_main_level()>0 ? MB_IMMRETURN : 0));
}
void QuitGame(GtkWidget *widget,gpointer data) {
t@@ -1795,8 +1796,10 @@ char GtkLoop(int *argc,char **argv[],gboolean ReturnOnFail) {
ClientMessageHandlerPt = HandleClientMessage;
/* Have the GLib log messages pop up in a nice dialog box */
- g_log_set_handler(NULL,LogMask()|G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_WARNING,
- LogMessage,NULL);
+ g_log_set_handler(NULL,LogMask()|G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_WARNING
+ | G_LOG_LEVEL_CRITICAL,LogMessage,NULL);
+
+ if (!CheckHighScoreFileConfig()) return TRUE;
/* Create the main player */
ClientData.Play=g_new(Player,1);
(DIR) diff --git a/src/gtkport.c b/src/gtkport.c
t@@ -45,7 +45,7 @@
HICON mainIcon=NULL;
static WNDPROC customWndProc=NULL;
-static gint RecurseLevel=0;
+static guint RecurseLevel=0;
static const gchar *WC_GTKSEP = "WC_GTKSEP";
static const gchar *WC_GTKVPANED = "WC_GTKVPANED";
t@@ -1061,6 +1061,10 @@ void win32_init(HINSTANCE hInstance,HINSTANCE hPrevInstance,char *MainIcon) {
InitCommonControls();
}
+guint gtk_main_level(void) {
+ return RecurseLevel;
+}
+
void gtk_widget_update(GtkWidget *widget,gboolean ForceResize) {
GtkRequisition req;
GtkWidget *window;
(DIR) diff --git a/src/gtkport.h b/src/gtkport.h
t@@ -722,6 +722,7 @@ void gtk_progress_bar_set_orientation(GtkProgressBar *pbar,
void gtk_progress_bar_update(GtkProgressBar *pbar,gfloat percentage);
guint gtk_timeout_add(guint32 interval,GtkFunction function,gpointer data);
void gtk_timeout_remove(guint timeout_handler_id);
+guint gtk_main_level(void);
#else /* CYGWIN */
(DIR) diff --git a/src/serverside.c b/src/serverside.c
t@@ -83,7 +83,7 @@ static char *attackquestiontr = N_("AE");
down our own server). */
#define METAMINTIME (60)
-int TerminateRequest,ReregisterRequest;
+int TerminateRequest,ReregisterRequest,RelogRequest;
int MetaUpdateTimeout;
int MetaMinTimeout;
t@@ -565,6 +565,12 @@ void ReregisterHandle(int sig) {
ReregisterRequest=1;
}
+void RelogHandle(int sig) {
+/* Responds to a SIGHUP signal, and requests the main event loop to
+ close and then reopen the log file (if any). */
+ RelogRequest=1;
+}
+
void BreakHandle(int sig) {
/* Traps an attempt by the user to send dopewars a SIGTERM or SIGINT */
/* (e.g. pressing Ctrl-C) and signals for a "nice" shutdown. Restores */
t@@ -616,41 +622,20 @@ static void ServerReply(const gchar *msg) {
void ServerHelp(void) {
/* Displays a simple help screen listing the server commands and options */
- int i;
-//#if CYGWIN || GUI_SERVER
- int Lines;
- GString *VarName;
- VarName=g_string_new("");
- g_print(_(HelpText),VERSION);
- Lines=16;
- for (i=0;i<NUMGLOB;i++) {
- if (Globals[i].NameStruct[0]) {
- g_string_sprintf(VarName,"%s%s.%s",Globals[i].NameStruct,
- Globals[i].StructListPt ? "[x]" : "",Globals[i].Name);
- } else {
- g_string_assign(VarName,Globals[i].Name);
- }
- g_print("%-26s\t%s\n",VarName->str,_(Globals[i].Help));
- Lines++;
-/*#ifndef GUI_SERVER
- if (Lines%24==0) {
- g_print(_("--More--")); bgetch(); g_print("\n");
- }
-endif*/
- }
- g_string_free(VarName,TRUE);
-/*#else
- FILE *fp;
- fp=popen(Pager,"w");
- if (fp) {
- PrintHelpTo(fp);
- i=pclose(fp);
- if (i==-1 || (WIFEXITED(i) && WEXITSTATUS(i)==127)) {
- g_warning(_("Pager exited abnormally - using stdout instead..."));
- PrintHelpTo(stdout);
- }
- }
-endif*/
+ int i;
+ GString *VarName;
+ VarName=g_string_new("");
+ g_print(_(HelpText),VERSION);
+ for (i=0;i<NUMGLOB;i++) {
+ if (Globals[i].NameStruct[0]) {
+ g_string_sprintf(VarName,"%s%s.%s",Globals[i].NameStruct,
+ Globals[i].StructListPt ? "[x]" : "",Globals[i].Name);
+ } else {
+ g_string_assign(VarName,Globals[i].Name);
+ }
+ g_print("%-26s\t%s\n",VarName->str,_(Globals[i].Help));
+ }
+ g_string_free(VarName,TRUE);
}
#if NETWORKING
t@@ -677,42 +662,7 @@ void RemovePidFile(void) {
if (PidFile) unlink(PidFile);
}
-gboolean ReadServerKey(GString *LineBuf,gboolean *EndOfLine) {
- int ch;
- *EndOfLine=FALSE;
-#ifdef CYGWIN
- ch=bgetch();
- if (ch=='\0') {
- return FALSE;
- } else if (ch=='\r') {
- g_print("\n");
- *EndOfLine=TRUE;
- return TRUE;
- } else if (ch==8) {
- if (strlen(LineBuf->str)>0) {
- g_print("\010 \010");
- g_string_truncate(LineBuf,strlen(LineBuf->str)-1);
- }
- return TRUE;
- }
- g_string_append_c(LineBuf,(gchar)ch);
- g_print("%c",ch);
- return TRUE;
-#else
- while (1) {
- ch=getchar();
- if (ch==EOF) return FALSE;
- else if (ch=='\n') {
- *EndOfLine=TRUE;
- break;
- }
- g_string_append_c(LineBuf,(gchar)ch);
- }
- return TRUE;
-#endif
-}
-
-static void StartServer(void) {
+static gboolean StartServer(void) {
LastError *sockerr=NULL;
GString *errstr;
#ifndef CYGWIN
t@@ -721,6 +671,7 @@ static void StartServer(void) {
SERVICE_STATUS status;
#endif
+ if (!CheckHighScoreFileConfig()) return FALSE;
Scanner=g_scanner_new(&ScannerConfig);
Scanner->msg_handler=ScannerErrorHandler;
Scanner->input_name="(stdin)";
t@@ -776,7 +727,7 @@ static void StartServer(void) {
MetaUpdateTimeout=MetaMinTimeout=0;
- TerminateRequest=ReregisterRequest=0;
+ TerminateRequest=ReregisterRequest=RelogRequest=0;
#if !CYGWIN
sact.sa_handler=ReregisterHandle;
t@@ -786,6 +737,12 @@ static void StartServer(void) {
/* Warning messages displayed if we fail to trap various signals */
g_warning(_("Cannot install SIGUSR1 interrupt handler!"));
}
+ sact.sa_handler=RelogHandle;
+ sact.sa_flags=0;
+ sigemptyset(&sact.sa_mask);
+ if (sigaction(SIGHUP,&sact,NULL)==-1) {
+ g_warning(_("Cannot install SIGHUP interrupt handler!"));
+ }
sact.sa_handler=BreakHandle;
sact.sa_flags=0;
sigemptyset(&sact.sa_mask);
t@@ -795,9 +752,6 @@ static void StartServer(void) {
if (sigaction(SIGTERM,&sact,NULL)==-1) {
g_warning(_("Cannot install SIGTERM interrupt handler!"));
}
- if (sigaction(SIGHUP,&sact,NULL)==-1) {
- g_warning(_("Cannot install SIGHUP interrupt handler!"));
- }
sact.sa_handler=SIG_IGN;
sact.sa_flags=0;
if (sigaction(SIGPIPE,&sact,NULL)==-1) {
t@@ -806,6 +760,7 @@ static void StartServer(void) {
#endif
RegisterWithMetaServer(TRUE,TRUE,FALSE);
+ return TRUE;
}
void RequestServerShutdown(void) {
t@@ -978,19 +933,22 @@ void ServerLoop() {
fd_set readfs,writefs,errorfs;
int topsock;
GPrintFunc oldprint;
-// gboolean InputClosed=FALSE;
struct timeval timeout;
int MinTimeout;
GString *LineBuf;
- gboolean /*EndOfLine,*/DoneOK;
+ gboolean DoneOK;
gchar *buf;
#ifndef CYGWIN
int localsock;
#endif
-// if (fork()>0) return;
+ if (!StartServer()) return;
- StartServer();
+#ifdef HAVE_FORK
+/* Daemonize; continue if the fork was successful and we are the child, or
+ if the fork failed */
+ if (Daemonize && fork()>0) return;
+#endif
#ifndef CYGWIN
localsock=SetupLocalSocket();
t@@ -1001,7 +959,6 @@ void ServerLoop() {
FD_ZERO(&readfs);
FD_ZERO(&writefs);
FD_ZERO(&errorfs);
-// if (!InputClosed) FD_SET(0,&readfs);
FD_SET(ListenSock,&readfs);
FD_SET(ListenSock,&errorfs);
topsock=ListenSock+1;
t@@ -1038,29 +995,20 @@ void ServerLoop() {
RegisterWithMetaServer(TRUE,TRUE,FALSE);
continue;
} else if (TerminateRequest) {
+ TerminateRequest=0;
RequestServerShutdown();
if (IsServerShutdown()) break;
else continue;
+ } else if (RelogRequest) { /* Re-open log file */
+ RelogRequest=0;
+ CloseLog();
+ OpenLog();
+ continue;
} else continue;
}
perror("select"); bgetch(); break;
}
FirstServer=HandleTimeouts(FirstServer);
-/* if (FD_ISSET(0,&readfs)) {
- if (ReadServerKey(LineBuf,&EndOfLine)==FALSE) {
- if (isatty(0)) {
- RequestServerShutdown();
- if (IsServerShutdown()) break;
- } else {
- dopelog(0,_("Standard input closed."));
- InputClosed=TRUE;
- }
- } else if (EndOfLine) {
- HandleServerCommand(LineBuf->str);
- if (IsServerShutdown()) break;
- g_string_truncate(LineBuf,0);
- }
- }*/
if (FD_ISSET(ListenSock,&readfs)) {
HandleNewConnection();
}
t@@ -1476,7 +1424,7 @@ void GuiServerLoop(gboolean is_service) {
g_log_set_handler(NULL,LogMask()|G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_WARNING,
GuiServerLogMessage,NULL);
}
- StartServer();
+ if (!StartServer()) return;
ListenTag=gdk_input_add(ListenSock,GDK_INPUT_READ,GuiNewConnect,NULL);
#ifdef CYGWIN
t@@ -1540,11 +1488,11 @@ void HighScoreTypeWrite(struct HISCORE *HiScore,FILE *fp) {
}
void CloseHighScoreFile() {
-/* Closes the high score file opened by InitHighScoreFile, below */
+/* Closes the high score file opened by OpenHighScoreFile, below */
if (ScoreFP) fclose(ScoreFP);
}
-static void DropPrivileges() {
+void DropPrivileges() {
/* If we're running setuid/setgid, drop down to the privilege level of the */
/* user that started the dopewars process */
#ifndef CYGWIN
t@@ -1648,45 +1596,70 @@ void ConvertHighScoreFile(void) {
g_free(BackupFile);
}
-int InitHighScoreFile(void) {
-/* Opens the high score file for later use, and then drops privileges. */
-/* If the high score file cannot be found, returns -1 (0=success) */
- gboolean NewFile=FALSE;
- char *OpenError=NULL;
+/* State, set by OpenHighScoreFile, and later used by
+ CheckHighScoreFileConfig */
+static gboolean NewFile;
+static int OpenError;
- if (ScoreFP) return 0; /* If already opened, then we're done */
+void OpenHighScoreFile(void) {
+/* Opens the high score file for later use, and then drops privileges. */
- /* Win32 gets upset if we use "a+" so we use this nasty hack instead */
- ScoreFP=fopen(HiScoreFile,"r+");
- if (!ScoreFP) {
- ScoreFP=fopen(HiScoreFile,"w+");
- if (!ScoreFP) OpenError=strerror(errno);
- NewFile=TRUE;
- }
+ NewFile=FALSE; OpenError=0;
- DropPrivileges();
+ if (ScoreFP) return; /* If already opened, then we're done */
- if (!ScoreFP) {
- g_log(NULL,G_LOG_LEVEL_CRITICAL,_("Cannot open high score file %s.\n"
- "(%s.) Either ensure you have permissions to access\n"
- "this file and directory, or specify an alternate high score "
- "file with the\n-f command line option."),HiScoreFile,OpenError);
- return -1;
- }
+ /* Win32 gets upset if we use "a+" so we use this nasty hack instead */
+ ScoreFP=fopen(HiScoreFile,"r+");
+ if (!ScoreFP) {
+ ScoreFP=fopen(HiScoreFile,"w+");
+ if (!ScoreFP) OpenError=errno;
+ NewFile=TRUE;
+ }
- if (NewFile) {
- HighScoreWriteHeader(ScoreFP);
- fflush(ScoreFP);
- } else if (!HighScoreReadHeader(ScoreFP,NULL)) {
- g_log(NULL,G_LOG_LEVEL_CRITICAL,_("%s does not appear to be a valid\n"
- "high score file - please check it. If it is a high score file\n"
- "from an older version of dopewars, then first convert it to the\n"
- "new format by running \"dopewars -C %s\"\n"
- "from the command line."),HiScoreFile,HiScoreFile);
- return -1;
- }
+ DropPrivileges();
+}
- return 0;
+gboolean CheckHighScoreFileConfig(void) {
+/* Checks the high score file opened by OpenHighScoreFile, above. Also warns
+ the user about other problems encountered during startup. Returns
+ TRUE if it's valid; otherwise, returns FALSE. */
+
+ if (!ScoreFP) {
+ g_log(NULL,G_LOG_LEVEL_CRITICAL,_("Cannot open high score file %s.\n"
+ "(%s.) Either ensure you have permissions to access\n"
+ "this file and directory, or specify an alternate high score "
+ "file with the\n-f command line option."),HiScoreFile,
+ strerror(OpenError));
+ return FALSE;
+ }
+
+ if (NewFile) {
+ HighScoreWriteHeader(ScoreFP);
+ fflush(ScoreFP);
+ } else if (!HighScoreReadHeader(ScoreFP,NULL)) {
+ g_log(NULL,G_LOG_LEVEL_CRITICAL,_("%s does not appear to be a valid\n"
+ "high score file - please check it. If it is a high score file\n"
+ "from an older version of dopewars, then first convert it to the\n"
+ "new format by running \"dopewars -C %s\"\n"
+ "from the command line."),HiScoreFile,HiScoreFile);
+ return FALSE;
+ }
+
+ if (ConfigErrors) {
+#ifdef CYGWIN
+ g_warning(
+_("Errors were encountered during the reading of the configuration file.\n"
+"As as result, some settings may not work as expected. Please consult the\n"
+"file \"dopewars-log.txt\" for further details."));
+#else
+ g_warning(
+_("Errors were encountered during the reading of the configuration\n"
+"file. As a result, some settings may not work as expected. Please see the\n"
+"messages on standard output for further details."));
+#endif
+ }
+
+ return TRUE;
}
gboolean HighScoreRead(FILE *fp,struct HISCORE *MultiScore,
(DIR) diff --git a/src/serverside.h b/src/serverside.h
t@@ -55,7 +55,8 @@ void ClearFightTimeout(Player *Play);
int GetMinimumTimeout(GSList *First);
GSList *HandleTimeouts(GSList *First);
void ConvertHighScoreFile(void);
-int InitHighScoreFile(void);
+void OpenHighScoreFile(void);
+gboolean CheckHighScoreFileConfig(void);
void CloseHighScoreFile(void);
gboolean HighScoreRead(FILE *fp,struct HISCORE *MultiScore,
struct HISCORE *AntiqueScore,gboolean ReadHeader);
t@@ -68,6 +69,7 @@ void RunFromCombat(Player *Play,int ToLocation);
gboolean CanPlayerFire(Player *Play);
gboolean CanRunHere(Player *Play);
Player *GetNextShooter(Player *Play);
+void DropPrivileges(void);
#ifdef GUI_SERVER
void GuiServerLoop(gboolean is_service);
#endif
(DIR) diff --git a/src/winmain.c b/src/winmain.c
t@@ -145,141 +145,141 @@ static gchar *GetWindowsLocale(void) {
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
LPSTR lpszCmdParam,int nCmdShow) {
- gchar **split;
- int argc;
- gboolean is_service;
- gchar modpath[300],*lastslash;
+ gchar **split;
+ int argc;
+ gboolean is_service;
+ gchar modpath[300],*lastslash;
#ifdef ENABLE_NLS
- gchar *winlocale;
+ gchar *winlocale;
#endif
/* Are we running as an NT service? */
- is_service = (lpszCmdParam && strncmp(lpszCmdParam,"-N",2)==0);
-
- if (is_service) {
- modpath[0]='\0';
- GetModuleFileName(NULL,modpath,300);
- lastslash=strrchr(modpath,'\\');
- if (lastslash) *lastslash='\0';
- SetCurrentDirectory(modpath);
- }
+ is_service = (lpszCmdParam && strncmp(lpszCmdParam,"-N",2)==0);
+
+ if (is_service) {
+ modpath[0]='\0';
+ GetModuleFileName(NULL,modpath,300);
+ lastslash=strrchr(modpath,'\\');
+ if (lastslash) *lastslash='\0';
+ SetCurrentDirectory(modpath);
+ }
- LogFileStart();
- g_set_print_handler(LogFilePrintFunc);
+ LogFileStart();
+ g_set_print_handler(LogFilePrintFunc);
- g_log_set_handler(NULL,LogMask()|G_LOG_LEVEL_MESSAGE,
- ServerLogMessage,NULL);
+ g_log_set_handler(NULL,LogMask()|G_LOG_LEVEL_MESSAGE,ServerLogMessage,NULL);
- if (!is_service) {
- g_log_set_handler(NULL,G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL,
- LogMessage,NULL);
- }
+ if (!is_service) {
+ g_log_set_handler(NULL,G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL,
+ LogMessage,NULL);
+ }
#ifdef ENABLE_NLS
- winlocale=GetWindowsLocale();
- if (winlocale) putenv(winlocale);
+ winlocale=GetWindowsLocale();
+ if (winlocale) putenv(winlocale);
- setlocale(LC_ALL,"");
- bindtextdomain(PACKAGE,LOCALEDIR);
- textdomain(PACKAGE);
+ setlocale(LC_ALL,"");
+ bindtextdomain(PACKAGE,LOCALEDIR);
+ textdomain(PACKAGE);
#endif
/* Informational comment placed at the start of the Windows log file
(this is used for messages printed during processing of the config
files - under Unix these are just printed to stdout) */
- g_print(_("# This is the dopewars startup log, containing any\n"
- "# informative messages resulting from configuration\n"
- "# file processing and the like.\n\n"));
-
- split=g_strsplit(lpszCmdParam," ",0);
- argc=0;
- while (split[argc] && split[argc][0]) argc++;
-
- if (GeneralStartup(argc,split)==0) {
- if (WantVersion || WantHelp) {
- WindowPrintStart();
- g_set_print_handler(WindowPrintFunc);
- HandleHelpTexts();
- WindowPrintEnd();
+ g_print(_("# This is the dopewars startup log, containing any\n"
+ "# informative messages resulting from configuration\n"
+ "# file processing and the like.\n\n"));
+
+ split=g_strsplit(lpszCmdParam," ",0);
+ argc=0;
+ while (split[argc] && split[argc][0]) argc++;
+
+ GeneralStartup(argc,split);
+ OpenLog();
+ if (WantVersion || WantHelp) {
+ WindowPrintStart();
+ g_set_print_handler(WindowPrintFunc);
+ HandleHelpTexts();
+ WindowPrintEnd();
#ifdef NETWORKING
- } else if (is_service) {
- StartNetworking();
-Network=Server=TRUE;
- win32_init(hInstance,hPrevInstance,"mainicon");
- ServiceMain();
- StopNetworking();
+ } else if (is_service) {
+ StartNetworking();
+ Network=Server=TRUE;
+ win32_init(hInstance,hPrevInstance,"mainicon");
+ ServiceMain();
+ StopNetworking();
#endif
- } else if (WantConvert) {
- WindowPrintStart();
- g_set_print_handler(WindowPrintFunc);
- ConvertHighScoreFile();
- WindowPrintEnd();
- } else {
+ } else if (WantConvert) {
+ WindowPrintStart();
+ g_set_print_handler(WindowPrintFunc);
+ ConvertHighScoreFile();
+ WindowPrintEnd();
+ } else {
#ifdef NETWORKING
- StartNetworking();
+ StartNetworking();
#endif
- if (Server) {
+ if (Server) {
#ifdef NETWORKING
#ifdef GUI_SERVER
- g_log_set_handler(NULL,G_LOG_LEVEL_CRITICAL,LogMessage,NULL);
- win32_init(hInstance,hPrevInstance,"mainicon");
- GuiServerLoop(FALSE);
+ g_log_set_handler(NULL,G_LOG_LEVEL_CRITICAL,LogMessage,NULL);
+ win32_init(hInstance,hPrevInstance,"mainicon");
+ GuiServerLoop(FALSE);
#else
- AllocConsole();
- SetConsoleTitle(_("dopewars server"));
- g_log_set_handler(NULL,
- LogMask()|G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_WARNING,
- ServerLogMessage,NULL);
- g_set_print_handler(ServerPrintFunc);
- newterm(NULL,NULL,NULL);
- ServerLoop();
+ AllocConsole();
+ SetConsoleTitle(_("dopewars server"));
+ g_log_set_handler(NULL,
+ LogMask()|G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_WARNING,
+ ServerLogMessage,NULL);
+ g_set_print_handler(ServerPrintFunc);
+ newterm(NULL,NULL,NULL);
+ ServerLoop();
#endif /* GUI_SERVER */
#else
- WindowPrintStart();
- g_set_print_handler(WindowPrintFunc);
- g_print(_("This binary has been compiled without networking "
- "support, and thus cannot run\nin server mode. "
- "Recompile passing --enable-networking to the "
- "configure script.\n"));
- WindowPrintEnd();
+ WindowPrintStart();
+ g_set_print_handler(WindowPrintFunc);
+ g_print(_("This binary has been compiled without networking "
+ "support, and thus cannot run\nin server mode. "
+ "Recompile passing --enable-networking to the "
+ "configure script.\n"));
+ WindowPrintEnd();
#endif /* NETWORKING */
- } else if (AIPlayer) {
- AllocConsole();
+ } else if (AIPlayer) {
+ AllocConsole();
/* Title of the Windows window used for AI player output */
- SetConsoleTitle(_("dopewars AI"));
-
- g_log_set_handler(NULL,
- LogMask()|G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_WARNING,
- ServerLogMessage,NULL);
- g_set_print_handler(ServerPrintFunc);
- newterm(NULL,NULL,NULL);
- AIPlayerLoop();
- } else if (WantedClient==CLIENT_CURSES) {
- AllocConsole();
- SetConsoleTitle(_("dopewars"));
- CursesLoop();
- } else {
+ SetConsoleTitle(_("dopewars AI"));
+
+ g_log_set_handler(NULL,
+ LogMask()|G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_WARNING,
+ ServerLogMessage,NULL);
+ g_set_print_handler(ServerPrintFunc);
+ newterm(NULL,NULL,NULL);
+ AIPlayerLoop();
+ } else if (WantedClient==CLIENT_CURSES) {
+ AllocConsole();
+ SetConsoleTitle(_("dopewars"));
+ CursesLoop();
+ } else {
#if GUI_CLIENT
- GtkLoop(hInstance,hPrevInstance);
+ GtkLoop(hInstance,hPrevInstance);
#else
- g_print(_("No graphical client available - rebuild the binary\n"
- "passing the --enable-gui-client option to configure, or\n"
- "use the curses client (if available) instead!\n"));
+ g_print(_("No graphical client available - rebuild the binary\n"
+ "passing the --enable-gui-client option to configure, or\n"
+ "use the curses client (if available) instead!\n"));
#endif
- }
+ }
#ifdef NETWORKING
- StopNetworking();
+ StopNetworking();
#endif
- }
- }
- LogFileEnd();
- g_strfreev(split);
- CloseHighScoreFile();
- g_free(PidFile);
- g_free(Log.File);
- g_free(ConvertFile);
- return 0;
+ }
+ CloseLog();
+ LogFileEnd();
+ g_strfreev(split);
+ CloseHighScoreFile();
+ g_free(PidFile);
+ g_free(Log.File);
+ g_free(ConvertFile);
+ return 0;
}
#endif /* CYGWIN */