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 */