tImproved logging functions added - 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 9911e27ee2e84f5bac7aa5707077b3e4497d9f0b
 (DIR) parent 64f33169c52a969f7eaa562684bce2d19f89dd4c
 (HTM) Author: Ben Webb <ben@salilab.org>
       Date:   Sun, 10 Jun 2001 01:19:26 +0000
       
       Improved logging functions added
       
       
       Diffstat:
         M ChangeLog                           |       1 +
         M src/curses_client.c                 |       2 +-
         M src/dopewars.c                      |      65 ++++++++++++++++++++++++++++++-
         M src/dopewars.h                      |      10 +++++++++-
         M src/gtk_client.c                    |       2 +-
         M src/message.c                       |      10 +++++++---
         M src/message.h                       |       2 +-
         M src/serverside.c                    |     102 ++++++++++++++++++-------------
         M src/winmain.c                       |      21 +++++++++++++--------
       
       9 files changed, 156 insertions(+), 59 deletions(-)
       ---
 (DIR) diff --git a/ChangeLog b/ChangeLog
       t@@ -1,4 +1,5 @@
        cvs
       +    - Improved logging in server via. LogLevel and LogTimestamp variables
            - Metaserver (both client and server) moved to SourceForge
            - Icons (courtesy of Ocelot Mantis) and GNOME desktop entry added
        
 (DIR) diff --git a/src/curses_client.c b/src/curses_client.c
       t@@ -1825,7 +1825,7 @@ void CursesLoop() {
           SocketWriteTestPt = NULL;
        
        /* Make the GLib log messages display nicely */
       -   g_log_set_handler(NULL,G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_WARNING,
       +   g_log_set_handler(NULL,LogMask()|G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_WARNING,
                             LogMessage,NULL);
        
           display_intro();
 (DIR) diff --git a/src/dopewars.c b/src/dopewars.c
       t@@ -37,6 +37,7 @@
        #include <curses_client.h>
        #include <gtk_client.h>
        #include <glib.h>
       +#include <stdarg.h>
        #include "dopeos.h"
        #include "message.h"
        #include "serverside.h"
       t@@ -161,6 +162,9 @@ int NumTurns=31;
        
        int PlayerArmour=100,BitchArmour=50;
        
       +int LogLevel=2;
       +gchar *LogTimestamp=NULL;
       +
        struct GLOBALS Globals[NUMGLOB] = {
        /* The following strings are the helptexts for all the options that can be
           set in a dopewars configuration file, or in the server. See
       t@@ -202,6 +206,12 @@ struct GLOBALS Globals[NUMGLOB] = {
           { &NumTurns,NULL,NULL,NULL,"NumTurns",
             N_("No. of game turns (if 0, game never ends)"),
             NULL,NULL,0,"",NULL,NULL },
       +   { &LogLevel,NULL,NULL,NULL,"LogLevel",
       +     N_("Controls the number of log messages produced"),
       +     NULL,NULL,0,"",NULL,NULL },
       +   { NULL,NULL,&LogTimestamp,NULL,"LogTimestamp",
       +     N_("strftime() format string for log timestamps"),
       +     NULL,NULL,0,"",NULL,NULL },
           { &Sanitized,NULL,NULL,NULL,"Sanitized",N_("Random events are sanitized"),
             NULL,NULL,0,"",NULL,NULL },
           { &DrugValue,NULL,NULL,NULL,"DrugValue",
       t@@ -622,7 +632,7 @@ GSList *AddPlayer(int fd,Player *NewPlayer,GSList *First) {
           NewPlayer->CoatSize=100;
           NewPlayer->Flags=0;
        #if NETWORKING
       -   InitNetworkBuffer(&NewPlayer->NetBuf,'\n');
       +   InitNetworkBuffer(&NewPlayer->NetBuf,'\n','\r');
           if (Server) BindNetworkBufferToSocket(&NewPlayer->NetBuf,fd);
        #endif
           InitAbilities(NewPlayer);
       t@@ -1056,6 +1066,21 @@ void RemoveAllEntries(DopeList *List,Player *Play) {
              RemoveListEntry(List,i);
           }
        }
       +
       +void dopelog(int loglevel,const gchar *format,...) {
       +/* General logging function. All messages should be given a loglevel, */
       +/* from 0 to 5 (0=vital, 2=normal, 5=maximum debugging output). This  */
       +/* is essentially just a wrapper around the GLib g_log function.      */
       +   va_list args;
       +   va_start (args,format);
       +   g_logv(G_LOG_DOMAIN,1<<(loglevel+G_LOG_LEVEL_USER_SHIFT),format,args);
       +   va_end (args);
       +}
       +
       +GLogLevelFlags LogMask() {
       +/* Returns the bitmask necessary to catch all custom log messages */
       +   return ((1<<(MAXLOG))-1) << G_LOG_LEVEL_USER_SHIFT;
       +}
             
        void ResizeLocations(int NewNum) {
           int i;
       t@@ -1575,9 +1600,11 @@ void SetupParameters() {
        
        /* Set hard-coded default values */
           g_free(HiScoreFile); g_free(ServerName); g_free(Pager);
       +   g_free(LogTimestamp);
           HiScoreFile=g_strdup_printf("%s/dopewars.sco",DATADIR);
           ServerName=g_strdup("localhost");
           Pager=g_strdup("more");
       +   LogTimestamp=g_strdup("[%H:%M:%S] ");
        
           CopyNames(&Names,&DefaultNames);
           CopyMetaServer(&MetaServer,&DefaultMetaServer);
       t@@ -1695,8 +1722,42 @@ int GeneralStartup(int argc,char *argv[]) {
           return 0;
        }
        
       +GString *GetLogString(GLogLevelFlags log_level,const gchar *message) {
       +/* Returns the text to be displayed in a log message, if any. */
       +   GString *text;
       +   gchar TimeBuf[80];
       +   gint i;
       +   time_t tim;
       +   struct tm *timep;
       +
       +   text=g_string_new("");
       +   if (LogTimestamp) {
       +      tim=time(NULL);
       +      timep=localtime(&tim);
       +      strftime(TimeBuf,80,LogTimestamp,timep);
       +      TimeBuf[79]='\0';
       +      g_string_append(text,TimeBuf);
       +   }
       +
       +   for (i=0;i<MAXLOG;i++) if (log_level&(1<<(G_LOG_LEVEL_USER_SHIFT+i))) {
       +      if (i>LogLevel) { g_string_free(text,TRUE); return NULL; }
       +      g_string_sprintfa(text,"%d: ",i);
       +   }
       +   g_string_append(text,message);
       +   return text;
       +}
       +
        #ifndef CYGWIN
        
       +static void ServerLogMessage(const gchar *log_domain,GLogLevelFlags log_level,
       +                             const gchar *message,gpointer user_data) {
       +   GString *text;
       +   text=GetLogString(log_level,message);
       +   if (text) {
       +      g_print("%s\n",text->str); g_string_free(text,TRUE);
       +   }
       +}
       +
        /* Standard program entry - Win32 uses WinMain() instead, in winmain.c */
        int main(int argc,char *argv[]) {
        #ifdef ENABLE_NLS
       t@@ -1715,6 +1776,8 @@ int main(int argc,char *argv[]) {
                    gtk_init(&argc,&argv);
                    GuiServerLoop();
        #else
       +/* Deal with dopelog() stuff nicely */
       +            g_log_set_handler(NULL,LogMask(),ServerLogMessage,NULL);
                    ServerLoop();
        #endif
                 } else if (AIPlayer) {
 (DIR) diff --git a/src/dopewars.h b/src/dopewars.h
       t@@ -127,6 +127,10 @@ extern struct NAMES Names;
        extern struct METASERVER MetaServer;
        extern int NumTurns;
        extern int PlayerArmour,BitchArmour;
       +extern int LogLevel;
       +extern gchar *LogTimestamp;
       +
       +#define MAXLOG        6
        
        #define DM_NONE       0
        #define DM_STREET     1
       t@@ -284,6 +288,7 @@ typedef struct tagConnBuf {
        typedef struct tagNetworkBuffer {
           int fd;                /* File descriptor of the socket */
           char Terminator;       /* Character that separates messages */
       +   char StripChar;        /* Character that should be removed from messages */
           ConnBuf ReadBuf;       /* New data, waiting for the application */
           ConnBuf WriteBuf;      /* Data waiting to be written to the wire */
           gboolean WaitConnect;  /* TRUE if a non-blocking connect is in progress */
       t@@ -332,7 +337,7 @@ typedef struct tag_serverdata {
           char *Comment,*Version,*Update,*UpSince;
        } ServerData;
        
       -#define NUMGLOB 87
       +#define NUMGLOB 89
        struct GLOBALS {
           int *IntVal;
           price_t *PriceVal;
       t@@ -418,4 +423,7 @@ void PrintConfigValue(int GlobalIndex,int StructIndex,gboolean IndexGiven,
        void SetConfigValue(int GlobalIndex,int StructIndex,gboolean IndexGiven,
                            GScanner *scanner);
        gboolean IsCop(Player *Play);
       +void dopelog(int loglevel,const gchar *format,...);
       +GLogLevelFlags LogMask();
       +GString *GetLogString(GLogLevelFlags log_level,const gchar *message);
        #endif
 (DIR) diff --git a/src/gtk_client.c b/src/gtk_client.c
       t@@ -1702,7 +1702,7 @@ char GtkLoop(int *argc,char **argv[],char ReturnOnFail) {
           SocketWriteTestPt = SetSocketWriteTest;
        
        /* Have the GLib log messages pop up in a nice dialog box */
       -   g_log_set_handler(NULL,G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_WARNING,
       +   g_log_set_handler(NULL,LogMask()|G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_WARNING,
                             LogMessage,NULL);
        
           ClientData.PlayerName=NULL;
 (DIR) diff --git a/src/message.c b/src/message.c
       t@@ -279,12 +279,14 @@ gboolean HaveAbility(Player *Play,gint Type) {
        }
        
        #if NETWORKING
       -void InitNetworkBuffer(NetworkBuffer *NetBuf,char Terminator) {
       +void InitNetworkBuffer(NetworkBuffer *NetBuf,char Terminator,char StripChar) {
        /* Initialises the passed network buffer, ready for use. Messages sent */
        /* or received on the buffered connection will be terminated by the    */
       -/* given character.                                                    */
       +/* given character, and if they end in "StripChar" it will be removed  */
       +/* before the messages are sent or received.                           */
           NetBuf->fd=-1;
           NetBuf->Terminator=Terminator;
       +   NetBuf->StripChar=StripChar;
           NetBuf->ReadBuf.Data=NetBuf->WriteBuf.Data=NULL;
           NetBuf->ReadBuf.Length=NetBuf->WriteBuf.Length=0;
           NetBuf->ReadBuf.DataPresent=NetBuf->WriteBuf.DataPresent=0;
       t@@ -329,7 +331,7 @@ void ShutdownNetworkBuffer(NetworkBuffer *NetBuf) {
        
           g_free(NetBuf->ReadBuf.Data);
           g_free(NetBuf->WriteBuf.Data);
       -   InitNetworkBuffer(NetBuf,NetBuf->Terminator);
       +   InitNetworkBuffer(NetBuf,NetBuf->Terminator,NetBuf->StripChar);
        }
        
        void SetSelectForNetworkBuffer(NetworkBuffer *NetBuf,fd_set *readfds,
       t@@ -445,6 +447,8 @@ gchar *GetWaitingMessage(NetworkBuffer *NetBuf) {
           if (!SepPt) return NULL;
           *SepPt='\0';
           MessageLen=SepPt-conn->Data+1;
       +   SepPt--;
       +   if (NetBuf->StripChar && *SepPt==NetBuf->StripChar) *SepPt='\0';
           NewMessage=g_new(gchar,MessageLen);
           memcpy(NewMessage,conn->Data,MessageLen);
           if (MessageLen<conn->DataPresent) {
 (DIR) diff --git a/src/message.h b/src/message.h
       t@@ -119,7 +119,7 @@ char *StartConnect(int *fd,gchar *RemoteHost,unsigned RemotePort,
                           gboolean NonBlocking);
        char *FinishConnect(int fd);
        
       -void InitNetworkBuffer(NetworkBuffer *NetBuf,char Terminator);
       +void InitNetworkBuffer(NetworkBuffer *NetBuf,char Terminator,char StripChar);
        gboolean IsNetworkBufferActive(NetworkBuffer *NetBuf);
        void BindNetworkBufferToSocket(NetworkBuffer *NetBuf,int fd);
        gboolean StartNetworkBufferConnect(NetworkBuffer *NetBuf,gchar *RemoteHost,
 (DIR) diff --git a/src/serverside.c b/src/serverside.c
       t@@ -149,7 +149,8 @@ void RegisterWithMetaServer(gboolean Up,gboolean SendData,
           if (!MetaServer.Active || !NotifyMetaServer || WantQuit) return;
        
           if (MetaMinTimeout > time(NULL) && RespectTimeout) {
       -      g_print("Attempt to connect to metaserver too frequently - waiting for next timeout\n");
       +      dopelog(3,_("Attempt to connect to metaserver too frequently "
       +                  "- waiting for next timeout"));
              MetaPlayerPending=TRUE;
              return;
           }
       t@@ -167,7 +168,8 @@ void RegisterWithMetaServer(gboolean Up,gboolean SendData,
           }
        
           if (StartNetworkBufferConnect(&MetaNetBuf,MetaName,MetaPort)) {
       -      g_print("Waiting for metaserver connect to %s:%d...\n",MetaName,MetaPort);
       +      dopelog(2,_("Waiting for metaserver connect to %s:%d..."),MetaName,
       +              MetaPort);
           } else return;
           MetaPlayerPending=FALSE;
           text=g_string_new("");
       t@@ -247,12 +249,12 @@ void HandleServerMessage(gchar *buf,Player *Play) {
           switch(Code) {
              case C_MSGTO:
                 if (Network) {
       -            g_message("%s->%s: %s",GetPlayerName(Play),GetPlayerName(To),Data);
       +            dopelog(3,"%s->%s: %s",GetPlayerName(Play),GetPlayerName(To),Data);
                 }
                 SendServerMessage(Play,AICode,Code,To,Data);
                 break;
              case C_NETMESSAGE:
       -         g_message("Net:%s\n",Data);
       +         dopelog(1,"Net:%s\n",Data);
        /*       shutdown(Play->fd,SD_RECV);*/
        /* Make sure they do actually disconnect, eventually! */
                 if (ConnectTimeout) {
       t@@ -285,7 +287,7 @@ void HandleServerMessage(gchar *buf,Player *Play) {
                       Play->ConnectTimeout=0;
        
                       if (Network) {
       -                  g_message(_("%s joins the game!"),GetPlayerName(Play));
       +                  dopelog(2,_("%s joins the game!"),GetPlayerName(Play));
                       }
                       for (list=FirstServer;list;list=g_slist_next(list)) {
                          pt=(Player *)list->data;
       t@@ -296,8 +298,8 @@ void HandleServerMessage(gchar *buf,Player *Play) {
                       SendEvent(Play);
                    } else {
        /* Message displayed in the server when too many players try to connect */
       -               g_message(_("MaxClients (%d) exceeded - dropping connection"),
       -                         MaxClients);
       +               dopelog(2,_("MaxClients (%d) exceeded - dropping connection"),
       +                       MaxClients);
                       if (MaxClients==1) {
                          text=g_strdup_printf(
        /* Message sent to a player if the server is full */
       t@@ -322,7 +324,7 @@ void HandleServerMessage(gchar *buf,Player *Play) {
                 } else {
        /* A player changed their name during the game (unusual, and not really
           properly supported anyway) - notify all players of the change */
       -            g_message(_("%s will now be known as %s"),GetPlayerName(Play),Data);
       +            dopelog(2,_("%s will now be known as %s"),GetPlayerName(Play),Data);
                    BroadcastToClients(C_NONE,C_RENAME,Data,Play,Play);
                    SetPlayerName(Play,Data);
                 }
       t@@ -341,6 +343,7 @@ void HandleServerMessage(gchar *buf,Player *Play) {
                    FinishGame(Play,_("Your dealing time is up..."));
                 } else if (i!=Play->IsAt && (NumTurns==0 || Play->Turn<NumTurns) && 
                            Play->EventNum==E_NONE && Play->Health>0) {
       +            dopelog(4,"%s jets to %s",GetPlayerName(Play),Location[i].Name);
                    Play->IsAt=(char)i;
                    Play->Turn++;
                    Play->Debt=(price_t)((float)Play->Debt*1.1);
       t@@ -351,7 +354,7 @@ void HandleServerMessage(gchar *buf,Player *Play) {
                 } else {
        /* A player has tried to jet to a new location, but we don't allow them to.
           (e.g. they're still fighting someone, or they're supposed to be dead) */
       -            g_warning(_("%s: DENIED jet to %s"),GetPlayerName(Play),
       +            dopelog(3,_("%s: DENIED jet to %s"),GetPlayerName(Play),
                                                        Location[i].Name);
                 }
                 break;
       t@@ -397,8 +400,8 @@ void HandleServerMessage(gchar *buf,Player *Play) {
                 break;
              case C_SPYON:
                 if (Play->Cash >= Prices.Spy) {
       -            g_message(_("%s now spying on %s"),GetPlayerName(Play),
       -                                            GetPlayerName(To));
       +            dopelog(3,_("%s now spying on %s"),GetPlayerName(Play),
       +                                               GetPlayerName(To));
                    Play->Cash -= Prices.Spy;
                    LoseBitch(Play,NULL,NULL);
                    NewEntry.Play=Play; NewEntry.Turns=-1;
       t@@ -411,7 +414,7 @@ void HandleServerMessage(gchar *buf,Player *Play) {
                 break;
              case C_TIPOFF:
                 if (Play->Cash >= Prices.Tipoff) {
       -            g_message(_("%s tipped off the cops to %s"),GetPlayerName(Play),
       +            dopelog(3,_("%s tipped off the cops to %s"),GetPlayerName(Play),
                                                                GetPlayerName(To));
                    Play->Cash -= Prices.Tipoff;
                    LoseBitch(Play,NULL,NULL);
       t@@ -430,7 +433,7 @@ void HandleServerMessage(gchar *buf,Player *Play) {
                 }
                 break;
              case C_MSG:
       -         if (Network) g_message("%s: %s",GetPlayerName(Play),Data);
       +         if (Network) dopelog(3,"%s: %s",GetPlayerName(Play),Data);
                 BroadcastToClients(C_NONE,C_MSG,Data,Play,Play);
                 break;
              default:
       t@@ -554,7 +557,7 @@ void CreatePidFile() {
           if (!PidFile) return;
           fp=fopen(PidFile,"w");
           if (fp) {
       -      g_message(_("Maintaining pid file %s"),PidFile);
       +      dopelog(1,_("Maintaining pid file %s"),PidFile);
              fprintf(fp,"%ld\n",(long)getpid());
              fclose(fp);
              chmod(PidFile,S_IREAD|S_IWRITE);
       t@@ -722,17 +725,17 @@ void HandleServerCommand(char *string) {
                       tmp=(Player *)list->data;
                       if (!IsCop(tmp)) g_print("%s\n",GetPlayerName(tmp));
                    }
       -         } else g_message(_("No users currently logged on!"));
       +         } else g_print(_("No users currently logged on!\n"));
              } else if (strncasecmp(string,"push ",5)==0) {
                 tmp=GetPlayerByName(string+5,FirstServer);
                 if (tmp) {
       -            g_message(_("Pushing %s"),GetPlayerName(tmp));
       +            dopelog(0,_("Pushing %s"),GetPlayerName(tmp));
                    SendServerMessage(NULL,C_NONE,C_PUSH,tmp,NULL);
                 } else g_warning(_("No such user!"));
              } else if (strncasecmp(string,"kill ",5)==0) {
                 tmp=GetPlayerByName(string+5,FirstServer);
                 if (tmp) {
       -            g_message(_("%s killed"),GetPlayerName(tmp));
       +            dopelog(0,_("%s killed"),GetPlayerName(tmp));
                    BroadcastToClients(C_NONE,C_KILL,GetPlayerName(tmp),tmp,
                                       (Player *)FirstServer->data);
                    FirstServer=RemovePlayer(tmp,FirstServer);
       t@@ -754,7 +757,7 @@ Player *HandleNewConnection() {
              perror("accept socket"); bgetch(); exit(1);
           }
           fcntl(ClientSock,F_SETFL,O_NONBLOCK);
       -   g_message(_("got connection from %s"),inet_ntoa(ClientAddr.sin_addr));
       +   dopelog(2,_("got connection from %s"),inet_ntoa(ClientAddr.sin_addr));
           tmp=g_new(Player,1);
           FirstServer=AddPlayer(ClientSock,tmp,FirstServer);
           if (ConnectTimeout) {
       t@@ -774,7 +777,7 @@ void RemovePlayerFromServer(Player *Play,gboolean WantQuit) {
           if (Play->InputTag) gdk_input_remove(Play->InputTag);
        #endif
           if (!WantQuit && strlen(GetPlayerName(Play))>0) {
       -      g_message(_("%s leaves the server!"),GetPlayerName(Play));
       +      dopelog(2,_("%s leaves the server!"),GetPlayerName(Play));
              ClientLeftServer(Play);
        /* Blank the name, so that CountPlayers ignores this player */
              SetPlayerName(Play,NULL);
       t@@ -797,13 +800,14 @@ void ServerLoop() {
           struct timeval timeout;
           int MinTimeout;
           GString *LineBuf;
       -   gboolean EndOfLine,DoneOK;
       +   gboolean EndOfLine,DoneOK,ReadingHeaders;
           gchar *buf;
        
       -   InitNetworkBuffer(&MetaNetBuf,'\n');
       +   InitNetworkBuffer(&MetaNetBuf,'\n','\r');
        
           StartServer();
        
       +   ReadingHeaders=TRUE;
           LineBuf=g_string_new("");
           while (1) {
              FD_ZERO(&readfs);
       t@@ -849,7 +853,7 @@ void ServerLoop() {
                       RequestServerShutdown();
                       if (IsServerShutdown()) break;
                    } else {
       -               g_message(_("Standard input closed."));
       +               dopelog(0,_("Standard input closed."));
                       InputClosed=TRUE;
                    }
                 } else if (EndOfLine) {
       t@@ -861,14 +865,18 @@ void ServerLoop() {
              if (FD_ISSET(ListenSock,&readfs)) {
                 HandleNewConnection();
              }
       +      if (MetaNetBuf.WaitConnect) ReadingHeaders=TRUE;
              if (RespondToSelect(&MetaNetBuf,&readfs,&writefs,&errorfs,&DoneOK)) {
                 while ((buf=GetWaitingMessage(&MetaNetBuf))) {
       -            g_print("Meta: %s\n",buf);
       +            if (buf[0] || ReadingHeaders) {
       +               dopelog(ReadingHeaders ? 4 : 2,"MetaServer: %s",buf);
       +            }
       +            if (buf[0]==0) ReadingHeaders=FALSE;
                    g_free(buf);
                 }
              }
              if (!DoneOK) {
       -         g_print("Meta: (closed)\n");
       +         dopelog(4,"MetaServer: (closed)\n");
                 ShutdownNetworkBuffer(&MetaNetBuf);
                 if (IsServerShutdown()) break;
              }
       t@@ -944,10 +952,13 @@ static void GuiServerPrintFunc(const gchar *string) {
        static void GuiServerLogMessage(const gchar *log_domain,
                                        GLogLevelFlags log_level,const gchar *message,
                                        gpointer user_data) {
       -   gchar *text;
       -   text = g_strdup_printf("Message: %s\n",message);
       -   GuiServerPrintFunc(text);
       -   g_free(text);
       +   GString *text;
       +   text=GetLogString(log_level,message);
       +   if (text) {
       +      g_string_append(text,"\n");
       +      GuiServerPrintFunc(text->str);
       +      g_string_free(text,TRUE);
       +   }
        }
        
        static void GuiQuitServer() {
       t@@ -1048,7 +1059,7 @@ void GuiServerLoop() {
           gtk_widget_show_all(window);
        
           g_set_print_handler(GuiServerPrintFunc);
       -   g_log_set_handler(NULL,G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_WARNING,
       +   g_log_set_handler(NULL,LogMask()|G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_WARNING,
                             GuiServerLogMessage,NULL);
           StartServer();
        
       t@@ -1189,6 +1200,7 @@ void SendHighScores(Player *Play,char EndGame,char *Message) {
              timep=gmtime(&tim);
              Score.Time=g_new(char,80); /* Yuck! */
              strftime(Score.Time,80,"%d-%m-%Y",timep);
       +      Score.Time[79]='\0';
              for (i=0;i<NUMHISCORE;i++) {
                 if (InList==-1 && (Score.Money > HiScore[i].Money ||
                     !HiScore[i].Time || HiScore[i].Time[0]==0)) {
       t@@ -1276,16 +1288,16 @@ void SendEvent(Player *To) {
                 case E_OFFOBJECT:
                    To->OnBehalfOf=NULL;
                    for (i=0;i<To->TipList.Number;i++) {
       -               g_message(_("%s: Tipoff from %s"),GetPlayerName(To),
       -                         GetPlayerName(To->TipList.Data[i].Play));
       +               dopelog(3,_("%s: Tipoff from %s"),GetPlayerName(To),
       +                       GetPlayerName(To->TipList.Data[i].Play));
                       To->OnBehalfOf=To->TipList.Data[i].Play;
                       SendCopOffer(To,FORCECOPS);
                       return;
                    }
                    for (i=0;i<To->SpyList.Number;i++) {
                       if (To->SpyList.Data[i].Turns<0) {
       -                  g_message(_("%s: Spy offered by %s"),GetPlayerName(To),
       -                            GetPlayerName(To->SpyList.Data[i].Play));
       +                  dopelog(3,_("%s: Spy offered by %s"),GetPlayerName(To),
       +                          GetPlayerName(To->SpyList.Data[i].Play));
                          To->OnBehalfOf=To->SpyList.Data[i].Play;
                          SendCopOffer(To,FORCEBITCH);
                          return;
       t@@ -1820,8 +1832,8 @@ void ResolveTipoff(Player *Play) {
           if (IsCop(Play) || !CanRunHere(Play)) return;
        
           if (g_slist_find(FirstServer,(gpointer)Play->OnBehalfOf)) {
       -      g_message(_("%s: tipoff by %s finished OK."),GetPlayerName(Play),
       -                GetPlayerName(Play->OnBehalfOf));
       +      dopelog(4,_("%s: tipoff by %s finished OK."),GetPlayerName(Play),
       +              GetPlayerName(Play->OnBehalfOf));
              RemoveListPlayer(&(Play->TipList),Play->OnBehalfOf);
              text=g_string_new("");
              if (Play->Health==0) {
       t@@ -1937,7 +1949,7 @@ int RandomOffer(Player *To) {
              SendPlayerData(To);
              SendPrintMessage(NULL,C_NONE,To,text->str);
           } else if (Sanitized) {
       -      g_message(_("Sanitized away a RandomOffer"));
       +      dopelog(3,_("Sanitized away a RandomOffer"));
           } else if (r<50) {
              amount=brandom(3,7);
              ind=IsCarryingRandom(To,amount);
       t@@ -2128,8 +2140,8 @@ void HandleAnswer(Player *From,Player *To,char *answer) {
           } else if (answer[0]=='Y') switch (From->EventNum) { 
              case E_OFFOBJECT:
                 if (g_slist_find(FirstServer,(gpointer)From->OnBehalfOf)) {
       -            g_message(_("%s: offer was on behalf of %s"),GetPlayerName(From),
       -                   GetPlayerName(From->OnBehalfOf));
       +            dopelog(3,_("%s: offer was on behalf of %s"),GetPlayerName(From),
       +                    GetPlayerName(From->OnBehalfOf));
                    if (From->Bitches.Price) {
                       text=dpg_strdup_printf(_("%s has accepted your %tde!"
                                              "^Use the G key to contact your spy."),
       t@@ -2224,8 +2236,8 @@ void HandleAnswer(Player *From,Player *To,char *answer) {
              case E_HIREBITCH: case E_GUNSHOP: case E_BANK: case E_LOANSHARK:
              case E_OFFOBJECT: case E_WEED:
                 if (g_slist_find(FirstServer,(gpointer)From->OnBehalfOf)) {
       -            g_message(_("%s: offer was on behalf of %s"),GetPlayerName(From),
       -                      GetPlayerName(From->OnBehalfOf));
       +            dopelog(3,_("%s: offer was on behalf of %s"),GetPlayerName(From),
       +                    GetPlayerName(From->OnBehalfOf));
                    if (From->Bitches.Price && From->EventNum==E_OFFOBJECT) {
                       text=dpg_strdup_printf(_("%s has rejected your %tde!"),
                                            GetPlayerName(From),Names.Bitch);
       t@@ -2431,9 +2443,13 @@ GSList *HandleTimeouts(GSList *First) {
           timenow=time(NULL);
           if (MetaMinTimeout<=timenow) {
              MetaMinTimeout=0;
       -      if (MetaPlayerPending) RegisterWithMetaServer(TRUE,TRUE,FALSE);
       +      if (MetaPlayerPending) {
       +         dopelog(3,_("Sending pending updates to the metaserver..."));
       +         RegisterWithMetaServer(TRUE,TRUE,FALSE);
       +      }
           }
           if (MetaUpdateTimeout!=0 && MetaUpdateTimeout<=timenow) {
       +      dopelog(3,_("Sending reminder message to the metaserver..."));
              RegisterWithMetaServer(TRUE,FALSE,FALSE);
           }
           list=First;
       t@@ -2442,7 +2458,7 @@ GSList *HandleTimeouts(GSList *First) {
              Play=(Player *)list->data;
              if (Play->IdleTimeout!=0 && Play->IdleTimeout<=timenow) {
                 Play->IdleTimeout=0;
       -         g_message(_("Player removed due to idle timeout"));
       +         dopelog(1,_("Player removed due to idle timeout"));
                 SendPrintMessage(NULL,C_NONE,Play,"Disconnected due to idle timeout");
                 ClientLeftServer(Play);
        /*       shutdown(Play->fd,SD_RECV);*/
       t@@ -2452,7 +2468,7 @@ GSList *HandleTimeouts(GSList *First) {
                 }
              } else if (Play->ConnectTimeout!=0 && Play->ConnectTimeout<=timenow) {
                 Play->ConnectTimeout=0;
       -         g_message(_("Player removed due to connect timeout"));
       +         dopelog(1,_("Player removed due to connect timeout"));
                 First=RemovePlayer(Play,First);
              } else if (Play->FightTimeout!=0 && Play->FightTimeout<=timenow) {
                 ClearFightTimeout(Play);
 (DIR) diff --git a/src/winmain.c b/src/winmain.c
       t@@ -42,11 +42,14 @@
        static void ServerLogMessage(const gchar *log_domain,GLogLevelFlags log_level,
                                     const gchar *message,gpointer user_data) {
           DWORD NumChar;
       -   gchar *text;
       -   text=g_strdup_printf("%s\n",message);
       -   WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),text,strlen(text),
       -                &NumChar,NULL);
       -   g_free(text);
       +   GString *text;
       +   text=GetLogString(log_level,message);
       +   if (text) {
       +      g_string_append(text,"\n");
       +      WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),text->str,strlen(text->str),
       +                   &NumChar,NULL);
       +      g_string_free(text,TRUE);
       +   }
        }
        
        static void ServerPrintFunc(const gchar *string) {
       t@@ -99,7 +102,7 @@ int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
           bindtextdomain(PACKAGE,LOCALEDIR);
           textdomain(PACKAGE);
        #endif
       -   g_log_set_handler(NULL,G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_WARNING|
       +   g_log_set_handler(NULL,LogMask()|G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_WARNING|
                             G_LOG_LEVEL_CRITICAL,LogMessage,NULL);
           split=g_strsplit(lpszCmdParam," ",0);
           argc=0;
       t@@ -129,7 +132,8 @@ int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
        #else
                    AllocConsole();
                    SetConsoleTitle(_("dopewars server"));
       -            g_log_set_handler(NULL,G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_WARNING,
       +            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);
       t@@ -141,7 +145,8 @@ int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
        /* Title of the Windows window used for AI player output */
                    SetConsoleTitle(_("dopewars AI"));
        
       -            g_log_set_handler(NULL,G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_WARNING,
       +            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);