tEncoding variable replaced by per-file "encoding" directive; configuration files are now read only when necessary (e.g. not when running "dopewars -v") and after client selection, so that it is no longer necessary to convert the codeset of configuration files - it is done on the fly when they are read in. - 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 9a0289056adce2040b8b5ddb09f5301ba65c2405
 (DIR) parent 9a9ff0d914d62a5f3dd56db880f7a1aca7887d20
 (HTM) Author: Ben Webb <ben@salilab.org>
       Date:   Mon, 12 Aug 2002 11:36:02 +0000
       
       Encoding variable replaced by per-file "encoding" directive; configuration
       files are now read only when necessary (e.g. not when running "dopewars -v")
       and after client selection, so that it is no longer necessary to convert
       tthe codeset of configuration files - it is done on the fly when they are
       read in.
       
       
       Diffstat:
         M ChangeLog                           |       5 +++--
         M TODO                                |       3 ---
         M doc/configfile.html                 |      25 ++++++++++++++++---------
         M src/AIPlayer.c                      |       4 ++--
         M src/AIPlayer.h                      |       3 ++-
         M src/admin.c                         |       5 ++++-
         M src/admin.h                         |       3 ++-
         M src/configfile.c                    |      43 +++----------------------------
         M src/configfile.h                    |       2 +-
         M src/curses_client/curses_client.c   |      10 ++++++----
         M src/curses_client/curses_client.h   |       4 +++-
         M src/dopewars.c                      |     263 ++++++++++++++++++++-----------
         M src/dopewars.h                      |      33 ++++++++++++++++++++-----------
         M src/gui_client/gtk_client.c         |       9 +++++----
         M src/gui_client/gtk_client.h         |       7 +++++--
         M src/serverside.c                    |      38 +++++++++++++++++++------------
         M src/serverside.h                    |       8 ++++----
         M src/winmain.c                       |      38 ++++++++++++++++---------------
       
       18 files changed, 293 insertions(+), 210 deletions(-)
       ---
 (DIR) diff --git a/ChangeLog b/ChangeLog
       t@@ -11,8 +11,9 @@ cvs
            - Names.Month and Names.Year have been replaced with StartDate.Day,
              StartDate.Month, StartDate.Year and Names.Date; these can be used to
              handle the date display properly after the turn number exceeds 31
       -    - Encoding config variable added, to allow the config file's encoding
       -      (usually taken from the locale) to be overridden
       +    - encoding and include config directives added, to allow the config file's
       +      encoding (usually taken from the locale) to be overridden, and to allow
       +      the inclusion of other config files
            - Spanish translation added by Quique
        
        1.5.7   25-06-2002
 (DIR) diff --git a/TODO b/TODO
       t@@ -1,6 +1,3 @@
       -- Fix the Encoding variable so that a) it works only on the current file
       -  (not on _all_ config files) and b) it only translates config file variables,
       -  not the defaults (which could be in a different codeset)
        - Limit rate of server connections to combat DOS attacks / players trying
          to get a good starting day?
        - Add support for reading/writing multiple configuration files to GUI client's
 (DIR) diff --git a/doc/configfile.html b/doc/configfile.html
       t@@ -68,6 +68,7 @@ locations</a></li>
        <li><a href="#drugs">Basic configuration: drug prices</a></li>
        <li><a href="#combat">Basic configuration: guns and fighting</a></li>
        <li><a href="#advanced">Advanced configuration</a></li>
       +<li><a href="#commands">Special configuration file commands</a></li>
        </ul>
        
        <h2><a id="fileloc">General configuration: file and server locations</a></h2>
       t@@ -645,15 +646,6 @@ feature.)</dd>
        <dd>If TRUE, then the server will keep track of the price you paid for
        any drugs, and clients will display this information if available.</dd>
        
       -<dt><b>Encoding=<i>"UTF-8"</i></b></dt>
       -<dd>Specifies that any text in the configuration files is in <i>"UTF-8"</i>
       -encoding. This variable is only supported if dopewars is built on a Unix
       -system and linked against GLib version 2. This influences both how the file
       -is read and written. If this variable is set to a blank string (the default)
       -then it will be assumed that your configuration files are in the locale's
       -default encoding - e.g. ISO-8859-1 for C or POSIX locales, ISO-8859-2 for pl_PL,
       -ISO-8859-15 for es_ES@euro, or UTF-8 for en_GB.UTF-8.</dd>
       -
        <dt><b>Sounds.FightHit=<i>"hit.wav"</i></b></dt>
        <dd>Plays the sound file <i>"hit.wav"</i> when you fire a gun and hit your
        target. The sound must be installed on your system, and you must be using
       t@@ -664,6 +656,21 @@ can be configured in the same way are: <b>FightMiss</b>, <b>FightReload</b>,
        
        </dl>
        
       +<h2><a id="commands">Special configuration file commands</a></h2>
       +<dl>
       +<dt><b>include <i>"foo"</i></b></dt>
       +<dd>Reads in the additional configuration file, <i>"foo"</i>.</dd>
       +
       +<dt><b>encoding <i>"UTF-8"</i></b></dt>
       +<dd>Specifies that any text following this directive (in this configuration
       +file only) is in <i>"UTF-8"</i> encoding. This directive is only supported
       +if dopewars is built on a Unix system and linked against GLib version 2.
       +If unspecifed, then it will be assumed that your configuration files are
       +in the locale's default encoding - e.g. ISO-8859-1 for C or POSIX locales,
       +ISO-8859-2 for pl_PL, ISO-8859-15 for es_ES@euro, or UTF-8 for en_GB.UTF-8.</dd>
       +
       +</dl>
       +
        <hr />
        <ul>
        <li><a href="index.html">Main index</a></li>
 (DIR) diff --git a/src/AIPlayer.c b/src/AIPlayer.c
       t@@ -132,7 +132,7 @@ static void NetBufAuth(NetworkBuffer *netbuf, gpointer data)
         * Main loop for AI players. Connects to server, plays game,
         * and then disconnects.
         */
       -void AIPlayerLoop()
       +void AIPlayerLoop(struct CMDLINE *cmdline)
        {
          GString *errstr;
          gchar *msg;
       t@@ -144,7 +144,7 @@ void AIPlayerLoop()
          NBSocksStatus oldsocks;
          NetworkBuffer *netbuf;
        
       -  ConvertConfigFile();
       +  InitConfiguration(cmdline);
        
          errstr = g_string_new("");
          AIPlay = g_new(Player, 1);
 (DIR) diff --git a/src/AIPlayer.h b/src/AIPlayer.h
       t@@ -27,6 +27,7 @@
        #include <config.h>
        #endif
        
       -void AIPlayerLoop(void);
       +struct CMDLINE;
       +void AIPlayerLoop(struct CMDLINE *cmdline);
        
        #endif /* __DP_AIPLAYER_H__ */
 (DIR) diff --git a/src/admin.c b/src/admin.c
       t@@ -36,6 +36,7 @@
        #include <stdio.h>
        #include <glib.h>
        
       +#include "dopewars.h"
        #include "network.h"
        #include "nls.h"
        #include "serverside.h"
       t@@ -73,7 +74,7 @@ static int OpenSocket(void)
          return sock;
        }
        
       -void AdminServer(void)
       +void AdminServer(struct CMDLINE *cmdline)
        {
          int sock, topsock;
          NetworkBuffer *netbuf;
       t@@ -81,6 +82,8 @@ void AdminServer(void)
          gchar *msg, inbuf[200];
          gboolean doneOK;
        
       +  InitConfiguration(cmdline);
       +
          sock = OpenSocket();
          netbuf = g_new(NetworkBuffer, 1);
        
 (DIR) diff --git a/src/admin.h b/src/admin.h
       t@@ -29,7 +29,8 @@
        
        #ifndef CYGWIN
        
       -void AdminServer(void);
       +struct CMDLINE;
       +void AdminServer(struct CMDLINE *cmdline);
        
        #endif /* CYGWIN */
        
 (DIR) diff --git a/src/configfile.c b/src/configfile.c
       t@@ -36,6 +36,8 @@
        #include "nls.h"                /* For _ function */
        #include "error.h"              /* For ErrStrFromErrno */
        
       +gchar *LocalCfgEncoding = NULL;
       +
        /*
         * Prints the given string to a file, converting control characters
         * and escaping other special characters.
       t@@ -194,8 +196,8 @@ static void WriteConfigFile(FILE *fp)
          int i, j;
          Converter *conv = Conv_New();
        
       -  if (Encoding && Encoding[0]) {
       -    Conv_SetCodeset(conv, Encoding);
       +  if (LocalCfgEncoding && LocalCfgEncoding[0]) {
       +    Conv_SetCodeset(conv, LocalCfgEncoding);
          }
        
          for (i = 0; i < NUMGLOB; i++) {
       t@@ -250,40 +252,3 @@ gboolean UpdateConfigFile(const gchar *cfgfile)
          g_free(defaultfile);
          return TRUE;
        }
       -
       -static void ConvertString(Converter *conv, gchar **str)
       -{
       -  AssignName(str, Conv_ToInternal(conv, *str, -1));
       -}
       -
       -void ConvertConfigFile(void)
       -{
       -  int i, j;
       -  struct GLOBALS *gvar;
       -  Converter *conv = Conv_New();
       -
       -  if (Encoding && Encoding[0]) {
       -    Conv_SetCodeset(conv, Encoding);
       -  }
       -
       -  if (Conv_Needed(conv)) {
       -    for (i = 0; i < NUMGLOB; i++) {
       -      gvar = &Globals[i];
       -      if (gvar->StringVal) {
       -        if (gvar->StructListPt) {
       -          for (j = 1; j <= *gvar->MaxIndex; j++) {
       -            ConvertString(conv, GetGlobalString(i, j));
       -          }
       -        } else {
       -          ConvertString(conv, GetGlobalString(i, 0));
       -        }
       -      } else if (gvar->StringList) {
       -        for (j = 0; j < *gvar->MaxIndex; j++) {
       -          ConvertString(conv, (*gvar->StringList) + j);
       -        }
       -      }
       -    }
       -  }
       -
       -  Conv_Free(conv);
       -}
 (DIR) diff --git a/src/configfile.h b/src/configfile.h
       t@@ -25,7 +25,7 @@
        
        #include <glib.h>
        
       +extern gchar *LocalCfgEncoding;
        gboolean UpdateConfigFile(const gchar *cfgfile);
       -void ConvertConfigFile(void);
        
        #endif /* __DP_CONFIGFILE_H__ */
 (DIR) diff --git a/src/curses_client/curses_client.c b/src/curses_client/curses_client.c
       t@@ -100,7 +100,7 @@ static void SocksAuthFunc(NetworkBuffer *netbuf, gpointer data);
        #endif
        
        static DispMode DisplayMode;
       -static gboolean QuitRequest;
       +static gboolean QuitRequest, WantColour = TRUE, WantNetwork = TRUE;
        
        /* 
         * Initialises the curses library for accessing the screen.
       t@@ -2418,7 +2418,7 @@ static void Curses_DoGame(Player *Play)
          g_string_free(text, TRUE);
        }
        
       -void CursesLoop(void)
       +void CursesLoop(struct CMDLINE *cmdline)
        {
          char c;
          Player *Play;
       t@@ -2426,7 +2426,9 @@ void CursesLoop(void)
          if (!CheckHighScoreFileConfig())
            return;
        
       -  ConvertConfigFile();
       +  InitConfiguration(cmdline);
       +  WantColour = cmdline->colour;
       +  WantNetwork = cmdline->network;
        
          /* Save the configuration, so we can restore those elements that get
           * overwritten when we connect to a dopewars server */
       t@@ -2444,7 +2446,7 @@ void CursesLoop(void)
                            G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_WARNING,
                            LogMessage, NULL);
        
       -  SoundOpen(WantedPlugin);
       +  SoundOpen(cmdline->plugin);
        
          display_intro();
        
 (DIR) diff --git a/src/curses_client/curses_client.h b/src/curses_client/curses_client.h
       t@@ -27,6 +27,8 @@
        #include <config.h>
        #endif
        
       -void CursesLoop(void);
       +struct CMDLINE;
       +
       +void CursesLoop(struct CMDLINE *cmdline);
        
        #endif
 (DIR) diff --git a/src/dopewars.c b/src/dopewars.c
       t@@ -41,6 +41,8 @@
        #include <glib.h>
        #include <stdarg.h>
        
       +#include "configfile.h"
       +#include "convert.h"
        #include "dopewars.h"
        #include "admin.h"
        #include "log.h"
       t@@ -66,7 +68,7 @@
        #endif
        
        int ClientSock, ListenSock;
       -gboolean Network, Client, Server, NotifyMetaServer, AIPlayer;
       +gboolean Network, Client, Server, WantAntique = FALSE;
        
        /* 
         * dopewars acting as standalone TCP server:
       t@@ -77,12 +79,9 @@ gboolean Network, Client, Server, NotifyMetaServer, AIPlayer;
         *           Network=Server=Client=FALSE
         */
        unsigned Port = 7902;
       -gboolean Sanitized, ConfigVerbose, DrugValue;
       +gboolean Sanitized, ConfigVerbose, DrugValue, Antique = FALSE;
        gchar *HiScoreFile = NULL, *ServerName = NULL, *ConvertFile = NULL;
       -gchar *ServerMOTD = NULL, *WantedPlugin = NULL, *BindAddress = NULL;
       -gchar *Encoding = NULL;
       -gboolean WantHelp, WantVersion, WantAntique, WantColour, WantNetwork;
       -gboolean WantConvert, WantAdmin;
       +gchar *ServerMOTD = NULL, *BindAddress = NULL;
        
        struct DATE StartDate = {
          1, 12, 1984
       t@@ -97,7 +96,6 @@ gboolean Daemonize = TRUE;
        gchar *WebBrowser = NULL;
        gint ConfigErrors = 0;
        
       -ClientType WantedClient;
        int NumLocation = 0, NumGun = 0, NumCop = 0, NumDrug = 0, NumSubway = 0;
        int NumPlaying = 0, NumStoppedTo = 0;
        int DebtInterest = 10, BankInterest = 5;
       t@@ -228,11 +226,6 @@ struct GLOBALS Globals[] = {
          /* The following strings are the helptexts for all the options that can
           * be set in a dopewars configuration file, or in the server. See
           * doc/configfile.html for more detailed explanations. */
       -#ifdef HAVE_GLIB2
       -  {NULL, NULL, NULL, &Encoding, NULL, "Encoding",
       -   N_("Charset encoding of the config file (e.g. UTF-8)"), NULL, NULL,
       -   0, "", NULL, NULL, FALSE, 0},
       -#endif
          {&Port, NULL, NULL, NULL, NULL, "Port", N_("Network port to connect to"),
           NULL, NULL, 0, "", NULL, NULL, FALSE, 0},
          {NULL, NULL, NULL, &HiScoreFile, NULL, "HiScoreFile",
       t@@ -770,6 +763,9 @@ char *DefaultSubwaySaying[] = {
          N_("Drugs can be your friend!")
        };
        
       +static gboolean SetConfigValue(int GlobalIndex, int StructIndex,
       +                               gboolean IndexGiven, Converter *conv,
       +                               GScanner *scanner);
        /* 
         * Returns a random integer not less than bot and less than top.
         */
       t@@ -1786,9 +1782,10 @@ void ScannerErrorHandler(GScanner *scanner, gchar *msg, gint error)
         * Read a configuration file given by "FileName"; GScanner under Win32
         * doesn't work properly with files, so we use a nasty workaround.
         */
       -static gboolean ReadConfigFile(char *FileName)
       +static gboolean ReadConfigFile(char *FileName, gchar **encoding)
        {
          FILE *fp;
       +  Converter *conv;
        
        #ifdef CYGWIN
          char *buf;
       t@@ -1797,6 +1794,10 @@ static gboolean ReadConfigFile(char *FileName)
        
          fp = fopen(FileName, "r");
          if (fp) {
       +    conv = Conv_New();
       +    if (encoding) {
       +      *encoding = NULL;
       +    }
            scanner = g_scanner_new(&ScannerConfig);
            scanner->input_name = FileName;
            scanner->msg_handler = ScannerErrorHandler;
       t@@ -1810,14 +1811,16 @@ static gboolean ReadConfigFile(char *FileName)
        #else
            g_scanner_input_file(scanner, fileno(fp));
        #endif
       -    while (!g_scanner_eof(scanner))
       -      if (!ParseNextConfig(scanner, FALSE)) {
       +    while (!g_scanner_eof(scanner)) {
       +      if (!ParseNextConfig(scanner, conv, encoding, FALSE)) {
                ConfigErrors++;
                g_scanner_error(scanner,
                                _("Unable to process configuration file %s, line %d"),
                                FileName, g_scanner_cur_line(scanner));
              }
       +    }
            g_scanner_destroy(scanner);
       +    Conv_Free(conv);
            fclose(fp);
        #ifdef CYGWIN
            g_free(buf);
       t@@ -1828,7 +1831,8 @@ static gboolean ReadConfigFile(char *FileName)
          }
        }
        
       -gboolean ParseNextConfig(GScanner *scanner, gboolean print)
       +gboolean ParseNextConfig(GScanner *scanner, Converter *conv,
       +                         gchar **encoding, gboolean print)
        {
          GTokenType token;
          gchar *ID1, *ID2;
       t@@ -1849,7 +1853,7 @@ gboolean ParseNextConfig(GScanner *scanner, gboolean print)
          if (g_strcasecmp(scanner->value.v_identifier, "include") == 0) {
            token = g_scanner_get_next_token(scanner);
            if (token == G_TOKEN_STRING) {
       -      if (!ReadConfigFile(scanner->value.v_string)) {
       +      if (!ReadConfigFile(scanner->value.v_string, NULL)) {
                g_scanner_error(scanner, _("Unable to open file %s"),
                                scanner->value.v_string);
              }
       t@@ -1859,6 +1863,20 @@ gboolean ParseNextConfig(GScanner *scanner, gboolean print)
                                    NULL, NULL, FALSE);
              return FALSE;
            }
       +  } else if (g_strcasecmp(scanner->value.v_identifier, "encoding") == 0) {
       +    token = g_scanner_get_next_token(scanner);
       +    if (token == G_TOKEN_STRING) {
       +      Conv_SetCodeset(conv, scanner->value.v_string);
       +      if (encoding) {
       +        g_free(*encoding);
       +        *encoding = g_strdup(scanner->value.v_string);
       +      }
       +      return TRUE;
       +    } else {
       +      g_scanner_unexp_token(scanner, G_TOKEN_STRING, NULL, NULL,
       +                            NULL, NULL, FALSE);
       +      return FALSE;
       +    }
          }
        
          ID1 = g_strdup(scanner->value.v_identifier);
       t@@ -1905,7 +1923,7 @@ gboolean ParseNextConfig(GScanner *scanner, gboolean print)
                          "players to log off, or remove\nthem with the "
                          "push or kill commands, and try again."));
            } else {
       -      if (SetConfigValue(GlobalIndex, (int)ind, IndexGiven, scanner)
       +      if (SetConfigValue(GlobalIndex, (int)ind, IndexGiven, conv, scanner)
                  && print) {
                PrintConfigValue(GlobalIndex, (int)ind, IndexGiven, scanner);
              }
       t@@ -2088,8 +2106,9 @@ void PrintConfigValue(int GlobalIndex, int StructIndex,
            g_free(GlobalName);
        }
        
       -gboolean SetConfigValue(int GlobalIndex, int StructIndex,
       -                        gboolean IndexGiven, GScanner *scanner)
       +static gboolean SetConfigValue(int GlobalIndex, int StructIndex,
       +                               gboolean IndexGiven, Converter *conv,
       +                               GScanner *scanner)
        {
          gchar *GlobalName, *tmpstr;
          GTokenType token;
       t@@ -2199,11 +2218,13 @@ gboolean SetConfigValue(int GlobalIndex, int StructIndex,
                G_CSET_LATINC;
            token = g_scanner_get_next_token(scanner);
            if (token == G_TOKEN_STRING) {
       -      AssignName(GetGlobalString(GlobalIndex, StructIndex),
       -                 scanner->value.v_string);
       +      tmpstr = Conv_ToInternal(conv, scanner->value.v_string, -1);
       +      AssignName(GetGlobalString(GlobalIndex, StructIndex), tmpstr);
       +      g_free(tmpstr);
            } else if (token == G_TOKEN_IDENTIFIER) {
       -      AssignName(GetGlobalString(GlobalIndex, StructIndex),
       -                 scanner->value.v_identifier);
       +      tmpstr = Conv_ToInternal(conv, scanner->value.v_identifier, -1);
       +      AssignName(GetGlobalString(GlobalIndex, StructIndex), tmpstr);
       +      g_free(tmpstr);
            } else {
              g_scanner_unexp_token(scanner, G_TOKEN_STRING, NULL, NULL,
                                    NULL, NULL, FALSE);
       t@@ -2216,8 +2237,10 @@ gboolean SetConfigValue(int GlobalIndex, int StructIndex,
            token = g_scanner_get_next_token(scanner);
            if (IndexGiven) {
              if (token == G_TOKEN_STRING) {
       +        tmpstr = Conv_ToInternal(conv, scanner->value.v_string, -1);
                AssignName(&(*(Globals[GlobalIndex].StringList))[StructIndex - 1],
       -                   scanner->value.v_string);
       +                   tmpstr);
       +        g_free(tmpstr);
              } else {
                g_scanner_unexp_token(scanner, G_TOKEN_STRING, NULL, NULL,
                                      NULL, NULL, FALSE);
       t@@ -2339,9 +2362,10 @@ gchar *GetLocalConfigFile(void)
         * hard-coded internal values, and then processes the global and
         * user-specific configuration files.
         */
       -void SetupParameters(void)
       +static void SetupParameters(GSList *extraconfigs)
        {
          gchar *conf;
       +  GSList *list;
          int i;
        
          /* Initialise variables */
       t@@ -2357,14 +2381,7 @@ void SetupParameters(void)
          NumLocation = NumGun = NumDrug = 0;
          FirstClient = FirstServer = NULL;
          Noone.Name = g_strdup("Noone");
       -  WantColour = WantNetwork = TRUE;
       -  WantHelp = WantConvert = WantVersion = WantAntique = WantAdmin = FALSE;
       -  WantedClient = CLIENT_AUTO;
       -  Server = AIPlayer = Client = Network = FALSE;
       -
       -  Log.Level = 2;
       -  Log.Timestamp = g_strdup("[%H:%M:%S] ");
       -  Log.File = g_strdup("");
       +  Server = Client = Network = FALSE;
        
          /* The currency symbol */
          Currency.Symbol = g_strdup(_("$"));
       t@@ -2376,11 +2393,9 @@ void SetupParameters(void)
          /* Set hard-coded default values */
          g_free(ServerName);
          g_free(ServerMOTD);
       -  g_free(Encoding);
          g_free(BindAddress);
          ServerName = g_strdup("localhost");
          ServerMOTD = g_strdup("");
       -  Encoding = g_strdup("");
          BindAddress = g_strdup("");
          g_free(WebBrowser);
          WebBrowser = g_strdup("/usr/bin/mozilla");
       t@@ -2436,16 +2451,21 @@ void SetupParameters(void)
          /* Now read in the global configuration file */
          conf = GetGlobalConfigFile();
          if (conf) {
       -    ReadConfigFile(conf);
       +    ReadConfigFile(conf, NULL);
            g_free(conf);
          }
        
       -  /* Finally, try the local configuration file */
       +  /* Next, try the local configuration file */
          conf = GetLocalConfigFile();
          if (conf) {
       -    ReadConfigFile(conf);
       +    ReadConfigFile(conf, &LocalCfgEncoding);
            g_free(conf);
          }
       +
       +  /* Finally, any configuration files named on the command line */
       +  for (list = extraconfigs; list; list = g_slist_next(list)) {
       +    ReadConfigFile(list->data, NULL);
       +  }
        }
        
        void GetDateString(GString *str, Player *Play)
       t@@ -2481,11 +2501,12 @@ static void PluginHelp(void)
          g_free(plugins);
        }
        
       -void HandleHelpTexts(void)
       +void HandleHelpTexts(gboolean fullhelp)
        {
          g_print(_("dopewars version %s\n"), VERSION);
       -  if (!WantHelp)
       +  if (!fullhelp) {
            return;
       +  }
        
          g_print(
        #ifdef HAVE_GETOPT_LONG
       t@@ -2561,9 +2582,10 @@ Report bugs to the author at ben@bellatrix.pcl.ox.ac.uk\n"));
        #endif
        }
        
       -void HandleCmdLine(int argc, char *argv[])
       +struct CMDLINE *ParseCmdLine(int argc, char *argv[])
        {
          int c;
       +  struct CMDLINE *cmdline = g_new0(struct CMDLINE, 1);
          static const gchar *options = "anbchvf:o:sSp:g:r:wtC:l:NAu:";
        
        #ifdef HAVE_GETOPT_LONG
       t@@ -2592,6 +2614,12 @@ void HandleCmdLine(int argc, char *argv[])
          };
        #endif
        
       +  cmdline->scorefile = cmdline->servername = cmdline->pidfile
       +      = cmdline->logfile = cmdline->plugin = cmdline->convertfile = NULL;
       +  cmdline->configs = NULL;
       +  cmdline->colour = cmdline->network = TRUE;
       +  cmdline->client = CLIENT_AUTO;
       +
          do {
        #ifdef HAVE_GETOPT_LONG
            c = getopt_long(argc, argv, options, long_options, NULL);
       t@@ -2600,80 +2628,101 @@ void HandleCmdLine(int argc, char *argv[])
        #endif
            switch (c) {
            case 'n':
       -      WantNetwork = FALSE;
       +      cmdline->network = FALSE;
              break;
            case 'b':
       -      WantColour = FALSE;
       +      cmdline->colour = FALSE;
              break;
            case 'c':
       -      AIPlayer = TRUE;
       +      cmdline->ai = TRUE;
              break;
            case 'a':
       -      WantAntique = TRUE;
       -      WantNetwork = FALSE;
       +      cmdline->antique = TRUE;
       +      cmdline->network = FALSE;
              break;
            case 'v':
       -      WantVersion = TRUE;
       +      cmdline->version = TRUE;
              break;
            case 'h':
            case 0:
            case '?':
       -      WantHelp = TRUE;
       +      cmdline->help = TRUE;
              break;
            case 'f':
       -      AssignName(&HiScoreFile, optarg);
       +      AssignName(&cmdline->scorefile, optarg);
              break;
            case 'o':
       -      AssignName(&ServerName, optarg);
       +      AssignName(&cmdline->servername, optarg);
              break;
            case 's':
       -      Server = TRUE;
       -      NotifyMetaServer = TRUE;
       +      cmdline->server = TRUE;
       +      cmdline->notifymeta = TRUE;
              break;
            case 'S':
       -      Server = TRUE;
       -      NotifyMetaServer = FALSE;
       +      cmdline->server = TRUE;
       +      cmdline->notifymeta = FALSE;
              break;
            case 'p':
       -      Port = atoi(optarg);
       +      cmdline->setport = TRUE;
       +      cmdline->port = atoi(optarg);
              break;
            case 'g':
       -      ReadConfigFile(optarg);
       +      cmdline->configs = g_slist_append(cmdline->configs, g_strdup(optarg));
              break;
            case 'r':
       -      AssignName(&PidFile, optarg);
       +      AssignName(&cmdline->pidfile, optarg);
              break;
            case 'l':
       -      AssignName(&Log.File, optarg);
       +      AssignName(&cmdline->logfile, optarg);
              break;
            case 'u':
       -      AssignName(&WantedPlugin, optarg);
       +      AssignName(&cmdline->plugin, optarg);
              break;
            case 'w':
       -      WantedClient = CLIENT_WINDOW;
       +      cmdline->client = CLIENT_WINDOW;
              break;
            case 't':
       -      WantedClient = CLIENT_CURSES;
       +      cmdline->client = CLIENT_CURSES;
              break;
            case 'C':
       -      AssignName(&ConvertFile, optarg);
       -      WantConvert = TRUE;
       +      AssignName(&cmdline->convertfile, optarg);
       +      cmdline->convert = TRUE;
              break;
            case 'A':
       -      WantAdmin = TRUE;
       +      cmdline->admin = TRUE;
              break;
            }
          } while (c != -1);
       +
       +  return cmdline;
        }
        
       +void FreeCmdLine(struct CMDLINE *cmdline)
       +{
       +  GSList *list;
       +
       +  g_free(cmdline->scorefile);
       +  g_free(cmdline->servername);
       +  g_free(cmdline->pidfile);
       +  g_free(cmdline->logfile);
       +  g_free(cmdline->plugin);
       +  g_free(cmdline->convertfile);
       +
       +  for (list = cmdline->configs; list; list = g_slist_next(list)) {
       +    g_free(list->data);
       +  }
       +  g_slist_free(list);
       +  g_free(cmdline);
       +}
       +
       +static gchar *priv_hiscore = NULL;
       +
        /* 
       - * Does general startup stuff (config. files, command line, and high
       - * score init.)
       + * Does general startup stuff (command line, dropping privileges,
       + * and high score init; config files are handled later)
         */
       -void GeneralStartup(int argc, char *argv[])
       +struct CMDLINE *GeneralStartup(int argc, char *argv[])
        {
       -  gchar *priv_hiscore;
       -
          /* First, open the hard-coded high score file with possibly
           * elevated privileges */
          priv_hiscore = g_strdup_printf("%s/dopewars.sco", DATADIR);
       t@@ -2681,11 +2730,40 @@ void GeneralStartup(int argc, char *argv[])
          OpenHighScoreFile();
          DropPrivileges();
        
       +  Log.File = g_strdup("");
       +  Log.Level = 2;
       +  Log.Timestamp = g_strdup("[%H:%M:%S] ");
       +
       +  return ParseCmdLine(argc, argv);
       +}
       +
       +void InitConfiguration(struct CMDLINE *cmdline)
       +{
          ConfigErrors = 0;
       -  SetupParameters();
       -  HandleCmdLine(argc, argv);
       +  SetupParameters(cmdline->configs);
       +
       +  if (cmdline->scorefile) {
       +    AssignName(&HiScoreFile, cmdline->scorefile);
       +  }
       +  if (cmdline->servername) {
       +    AssignName(&ServerName, cmdline->servername);
       +  }
       +  if (cmdline->pidfile) {
       +    AssignName(&PidFile, cmdline->pidfile);
       +  }
       +  if (cmdline->logfile) {
       +    AssignName(&Log.File, cmdline->logfile);
       +  }
       +  if (cmdline->setport) {
       +    Port = cmdline->port;
       +  }
       +  if (cmdline->server) {
       +    MetaServer.Active = cmdline->notifymeta;
       +  }
       +  WantAntique = cmdline->antique;
        
       -  if (!WantVersion && !WantHelp && !AIPlayer && !WantConvert && !WantAdmin) {
       +  if (!cmdline->version && !cmdline->help && !cmdline->ai
       +      && !cmdline->convert && !cmdline->admin) {
            /* Open a user-specified high score file with no privileges, if one
             * was given */
            if (strcmp(priv_hiscore, HiScoreFile) != 0) {
       t@@ -2695,7 +2773,6 @@ void GeneralStartup(int argc, char *argv[])
          } else {
            CloseHighScoreFile();
          }
       -  g_free(priv_hiscore);
        }
        
        /*
       t@@ -2790,6 +2867,7 @@ static void DefaultLogMessage(const gchar *log_domain,
         */
        int main(int argc, char *argv[])
        {
       +  struct CMDLINE *cmdline;
        #ifdef ENABLE_NLS
          setlocale(LC_ALL, "");
          bindtextdomain(PACKAGE, LOCALEDIR);
       t@@ -2797,26 +2875,27 @@ int main(int argc, char *argv[])
        #endif
          WantUTF8Errors(FALSE);
          g_log_set_handler(NULL, LogMask(), DefaultLogMessage, NULL);
       -  GeneralStartup(argc, argv);
       +  cmdline = GeneralStartup(argc, argv);
          OpenLog();
          SoundInit();
       -  if (WantVersion || WantHelp) {
       -    HandleHelpTexts();
       -  } else if (WantAdmin) {
       -    AdminServer();
       -  } else if (WantConvert) {
       -    ConvertHighScoreFile();
       +  if (cmdline->version || cmdline->help) {
       +    HandleHelpTexts(cmdline->help);
       +  } else if (cmdline->admin) {
       +    AdminServer(cmdline);
       +  } else if (cmdline->convert) {
       +    ConvertHighScoreFile(cmdline->convertfile);
          } else {
            InitNetwork();
       -    if (Server) {
       +    if (cmdline->server) {
        #ifdef NETWORKING
        #ifdef GUI_SERVER
       +      Server = TRUE;
              gtk_set_locale();
              gtk_init(&argc, &argv);
       -      GuiServerLoop(FALSE);
       +      GuiServerLoop(cmdline, FALSE);
        #else
              g_log_set_handler(NULL, LogMask(), ServerLogMessage, NULL);
       -      ServerLoop();
       +      ServerLoop(cmdline);
        #endif /* GUI_SERVER */
        #else
              g_print(_("This binary has been compiled without networking "
       t@@ -2824,30 +2903,30 @@ int main(int argc, char *argv[])
                        "Recompile passing --enable-networking to the "
                        "configure script.\n"));
        #endif /* NETWORKING */
       -    } else if (AIPlayer) {
       -      AIPlayerLoop();
       +    } else if (cmdline->ai) {
       +      AIPlayerLoop(cmdline);
            } else
       -      switch (WantedClient) {
       +      switch (cmdline->client) {
              case CLIENT_AUTO:
       -        if (!GtkLoop(&argc, &argv, TRUE))
       -          CursesLoop();
       +        if (!GtkLoop(&argc, &argv, cmdline, TRUE))
       +          CursesLoop(cmdline);
                break;
              case CLIENT_WINDOW:
       -        GtkLoop(&argc, &argv, FALSE);
       +        GtkLoop(&argc, &argv, cmdline, FALSE);
                break;
              case CLIENT_CURSES:
       -        CursesLoop();
       +        CursesLoop(cmdline);
                break;
              }
        #ifdef NETWORKING
            StopNetworking();
        #endif
          }
       +  FreeCmdLine(cmdline);
          CloseLog();
          CloseHighScoreFile();
          g_free(PidFile);
          g_free(Log.File);
       -  g_free(ConvertFile);
          SoundClose();
          return 0;
        }
 (DIR) diff --git a/src/dopewars.h b/src/dopewars.h
       t@@ -43,6 +43,7 @@
        #endif
        
        #include <glib.h>
       +#include "convert.h"
        #include "error.h"
        #include "network.h"
        #include "util.h"
       t@@ -169,25 +170,23 @@ struct DATE {
          int day, month, year;
        };
        
       +extern gboolean WantAntique;
        extern struct DATE StartDate;
        extern int ClientSock, ListenSock;
       -extern gboolean Network, Client, Server, NotifyMetaServer, AIPlayer;
       +extern gboolean Network, Client, Server;
        extern unsigned Port;
        extern gboolean Sanitized, ConfigVerbose, DrugValue;
        extern int NumLocation, NumGun, NumCop, NumDrug, NumSubway, NumPlaying,
                   NumStoppedTo;
        extern int DebtInterest, BankInterest;
        extern gchar *HiScoreFile, *ServerName, *ConvertFile, *ServerMOTD,
       -             *WantedPlugin, *BindAddress, *Encoding;
       -extern gboolean WantHelp, WantVersion, WantAntique, WantColour,
       -                WantNetwork, WantConvert, WantAdmin;
       +             *BindAddress;
        #ifdef CYGWIN
        extern gboolean MinToSysTray;
        #else
        extern gboolean Daemonize;
        #endif
        extern gchar *WebBrowser;
       -extern ClientType WantedClient;
        extern int LoanSharkLoc, BankLoc, GunShopLoc, RoughPubLoc;
        extern int DrugSortMethod, FightTimeout, IdleTimeout, ConnectTimeout;
        extern int MaxClients, AITurnPause;
       t@@ -353,6 +352,16 @@ struct GLOBALS {
          int MinVal;
        };
        
       +struct CMDLINE { 
       +  gboolean help, version, antique, colour, network;
       +  gboolean convert, admin, ai, server, notifymeta;
       +  gboolean setport;
       +  gchar *scorefile, *servername, *pidfile, *logfile, *plugin, *convertfile;
       +  unsigned port;
       +  ClientType client;
       +  GSList *configs;
       +};  
       +
        extern const int NUMGLOB;
        extern struct GLOBALS Globals[];
        
       t@@ -417,12 +426,14 @@ gchar *InitialCaps(gchar *string);
        char StartsWithVowel(char *string);
        char *GetPlayerName(Player *Play);
        void SetPlayerName(Player *Play, char *Name);
       -void HandleCmdLine(int argc, char *argv[]);
       -void SetupParameters(void);
       -void HandleHelpTexts(void);
       -void GeneralStartup(int argc, char *argv[]);
       +struct CMDLINE *ParseCmdLine(int argc, char *argv[]);
       +void FreeCmdLine(struct CMDLINE *cmdline);
       +void InitConfiguration(struct CMDLINE *cmdline);
       +void HandleHelpTexts(gboolean fullhelp);
       +struct CMDLINE *GeneralStartup(int argc, char *argv[]);
        void StripTerminators(gchar *str);
       -gboolean ParseNextConfig(GScanner *scanner, gboolean print);
       +gboolean ParseNextConfig(GScanner *scanner, Converter *conv,
       +                         gchar **encoding, gboolean print);
        int GetGlobalIndex(gchar *ID1, gchar *ID2);
        gchar **GetGlobalString(int GlobalIndex, int StructIndex);
        gint *GetGlobalInt(int GlobalIndex, int StructIndex);
       t@@ -431,8 +442,6 @@ gboolean *GetGlobalBoolean(int GlobalIndex, int StructIndex);
        gchar ***GetGlobalStringList(int GlobalIndex, int StructIndex);
        void PrintConfigValue(int GlobalIndex, int StructIndex,
                              gboolean IndexGiven, GScanner *scanner);
       -gboolean SetConfigValue(int GlobalIndex, int StructIndex,
       -                        gboolean IndexGiven, GScanner *scanner);
        gboolean IsCop(Player *Play);
        void RestoreConfig(void);
        void GetDateString(GString *str, Player *Play);
 (DIR) diff --git a/src/gui_client/gtk_client.c b/src/gui_client/gtk_client.c
       t@@ -2134,9 +2134,10 @@ static void make_tags(GtkTextView *textview)
        
        #ifdef CYGWIN
        gboolean GtkLoop(HINSTANCE hInstance, HINSTANCE hPrevInstance,
       -                 gboolean ReturnOnFail)
       +                 struct CMDLINE *cmdline, gboolean ReturnOnFail)
        #else
       -gboolean GtkLoop(int *argc, char **argv[], gboolean ReturnOnFail)
       +gboolean GtkLoop(int *argc, char **argv[],
       +                 struct CMDLINE *cmdline, gboolean ReturnOnFail)
        #endif
        {
          GtkWidget *window, *vbox, *vbox2, *hbox, *frame, *table, *menubar, *text,
       t@@ -2161,9 +2162,9 @@ gboolean GtkLoop(int *argc, char **argv[], gboolean ReturnOnFail)
          bind_textdomain_codeset(PACKAGE, "UTF-8");
        
          Conv_SetInternalCodeset("UTF-8");
       -  ConvertConfigFile();
          WantUTF8Errors(TRUE);
        #endif
       +  InitConfiguration(cmdline);
        
          /* Set up message handlers */
          ClientMessageHandlerPt = HandleClientMessage;
       t@@ -2176,7 +2177,7 @@ gboolean GtkLoop(int *argc, char **argv[], gboolean ReturnOnFail)
          if (!CheckHighScoreFileConfig())
            return TRUE;
        
       -  SoundOpen(WantedPlugin);
       +  SoundOpen(cmdline->plugin);
        
          /* Create the main player */
          ClientData.Play = g_new(Player, 1);
 (DIR) diff --git a/src/gui_client/gtk_client.h b/src/gui_client/gtk_client.h
       t@@ -31,11 +31,14 @@
        
        extern GtkWidget *MainWindow;
        
       +struct CMDLINE;
       +
        #ifdef CYGWIN
        gboolean GtkLoop(HINSTANCE hInstance, HINSTANCE hPrevInstance,
       -                 gboolean ReturnOnFail);
       +                 struct CMDLINE *cmdline, gboolean ReturnOnFail);
        #else
       -gboolean GtkLoop(int *argc, char **argv[], gboolean ReturnOnFail);
       +gboolean GtkLoop(int *argc, char **argv[],
       +                 struct CMDLINE *cmdline, gboolean ReturnOnFail);
        #endif
        
        void GuiStartGame(void);
 (DIR) diff --git a/src/serverside.c b/src/serverside.c
       t@@ -232,7 +232,7 @@ void RegisterWithMetaServer(gboolean Up, gboolean SendData,
          gboolean retval;
          int i;
        
       -  if (!MetaServer.Active || !NotifyMetaServer || WantQuit)
       +  if (!MetaServer.Active || WantQuit)
            return;
        
          if (MetaMinTimeout > time(NULL) && RespectTimeout) {
       t@@ -830,7 +830,6 @@ static gboolean StartServer(void)
          Scanner->msg_handler = ScannerErrorHandler;
          Scanner->input_name = "(stdin)";
          CreatePidFile();
       -  ConvertConfigFile();
        
          /* Make the output line-buffered, so that the log file (if used) is
           * updated regularly */
       t@@ -983,11 +982,13 @@ static void HandleServerCommand(char *string, NetworkBuffer *netbuf)
          GSList *list;
          Player *tmp;
          GPrintFunc oldprint;
       +  Converter *conv;
        
          oldprint = StartServerReply(netbuf);
        
       +  conv = Conv_New();
          g_scanner_input_text(Scanner, string, strlen(string));
       -  if (!ParseNextConfig(Scanner, TRUE)) {
       +  if (!ParseNextConfig(Scanner, conv, NULL, TRUE)) {
            if (g_strcasecmp(string, "help") == 0 || g_strcasecmp(string, "h") == 0
                || strcmp(string, "?") == 0) {
              ServerHelp();
       t@@ -1032,6 +1033,7 @@ static void HandleServerCommand(char *string, NetworkBuffer *netbuf)
              g_print(_("Unknown command - try \"help\" for help...\n"));
            }
          }
       +  Conv_Free(conv);
          FinishServerReply(oldprint);
        }
        
       t@@ -1148,7 +1150,7 @@ static int SetupLocalSocket(void)
         * Initialises server, processes network and interactive messages, and
         * finally cleans up the server on exit.
         */
       -void ServerLoop()
       +void ServerLoop(struct CMDLINE *cmdline)
        {
          Player *tmp;
          GSList *list, *listcp;
       t@@ -1167,6 +1169,8 @@ void ServerLoop()
          GSList *localconn = NULL;
        #endif
        
       +  InitConfiguration(cmdline);
       +
          if (!StartServer())
            return;
        
       t@@ -1609,7 +1613,7 @@ static VOID WINAPI ServiceInit(DWORD argc, LPTSTR * argv)
            return;
          }
        
       -  GuiServerLoop(TRUE);
       +  GuiServerLoop(NULL, TRUE);
        
          if (!RegisterStatus(SERVICE_STOPPED)) {
            dopelog(0, LF_SERVER, _("Failed to set NT Service status"));
       t@@ -1617,13 +1621,15 @@ static VOID WINAPI ServiceInit(DWORD argc, LPTSTR * argv)
          }
        }
        
       -void ServiceMain(void)
       +void ServiceMain(struct CMDLINE *cmdline)
        {
          SERVICE_TABLE_ENTRY services[] = {
            {"dopewars-server", ServiceInit},
            {NULL, NULL}
          };
        
       +  InitConfiguration(cmdline);
       +
          if (!StartServiceCtrlDispatcher(services)) {
            dopelog(0, LF_SERVER, _("Failed to start NT Service"));
          }
       t@@ -1678,10 +1684,14 @@ static void SetupTaskBarIcon(GtkWidget *widget)
        }
        #endif /* CYGWIN */
        
       -void GuiServerLoop(gboolean is_service)
       +void GuiServerLoop(struct CMDLINE *cmdline, gboolean is_service)
        {
          GtkWidget *window, *text, *hbox, *vbox, *entry, *label;
        
       +  if (cmdline) {
       +    InitConfiguration(cmdline);
       +  }
       +
          window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
          gtk_signal_connect(GTK_OBJECT(window), "delete_event",
                             GTK_SIGNAL_FUNC(GuiRequestDelete), NULL);
       t@@ -1871,7 +1881,7 @@ static void HighScoreWriteHeader(FILE *fp)
        /* 
         * Converts an old format high score file to the new format.
         */
       -void ConvertHighScoreFile(void)
       +void ConvertHighScoreFile(const gchar *convertfile)
        {
          FILE *old, *backup;
          gchar *BackupFile;
       t@@ -1879,9 +1889,9 @@ void ConvertHighScoreFile(void)
          gchar *OldError = NULL, *BackupError = NULL;
          struct HISCORE MultiScore[NUMHISCORE], AntiqueScore[NUMHISCORE];
        
       -  BackupFile = g_strdup_printf("%s.bak", ConvertFile);
       +  BackupFile = g_strdup_printf("%s.bak", convertfile);
        
       -  old = fopen(ConvertFile, "r+");
       +  old = fopen(convertfile, "r+");
          if (!old) {
            OldError = ErrStrFromErrno(errno);
          }
       t@@ -1899,7 +1909,7 @@ void ConvertHighScoreFile(void)
            if (HighScoreReadHeader(old, NULL)) {
              g_log(NULL, G_LOG_LEVEL_CRITICAL,
                    _("The high score file %s\n"
       -              "is already in the new format! Aborting."), ConvertFile);
       +              "is already in the new format! Aborting."), convertfile);
              fclose(old);
              fclose(backup);
            } else {
       t@@ -1920,14 +1930,14 @@ void ConvertHighScoreFile(void)
               * the header */
              if (!HighScoreRead(old, MultiScore, AntiqueScore, FALSE)) {
                g_log(NULL, G_LOG_LEVEL_CRITICAL,
       -              _("Error reading scores from %s."), ConvertFile);
       +              _("Error reading scores from %s."), convertfile);
              } else {
                ftruncate(fileno(old), 0);
                rewind(old);
                if (HighScoreWrite(old, MultiScore, AntiqueScore)) {
                  g_message(_("The high score file %s has been converted to the "
                              "new format.\nA backup of the old file has been "
       -                      "created as %s.\n"), ConvertFile, BackupFile);
       +                      "created as %s.\n"), convertfile, BackupFile);
                }
              }
              fclose(old);
       t@@ -1936,7 +1946,7 @@ void ConvertHighScoreFile(void)
            if (!old) {
              g_log(NULL, G_LOG_LEVEL_CRITICAL,
                    _("Cannot open high score file %s: %s."),
       -            ConvertFile, OldError);
       +            convertfile, OldError);
            } else if (!backup) {
              g_log(NULL, G_LOG_LEVEL_CRITICAL,
                    _("Cannot create backup (%s) of the\nhigh score file: %s."),
 (DIR) diff --git a/src/serverside.h b/src/serverside.h
       t@@ -37,7 +37,7 @@ void BreakHandle(int sig);
        void ClientLeftServer(Player *Play);
        void StopServer(void);
        Player *HandleNewConnection(void);
       -void ServerLoop(void);
       +void ServerLoop(struct CMDLINE *cmdline);
        void HandleServerPlayer(Player *Play);
        void HandleServerMessage(gchar *buf, Player *ReallyFrom);
        void FinishGame(Player *Play, char *Message);
       t@@ -54,7 +54,7 @@ void SetFightTimeout(Player *Play);
        void ClearFightTimeout(Player *Play);
        int GetMinimumTimeout(GSList *First);
        GSList *HandleTimeouts(GSList *First);
       -void ConvertHighScoreFile(void);
       +void ConvertHighScoreFile(const gchar *convertfile);
        void OpenHighScoreFile(void);
        gboolean CheckHighScoreFileConfig(void);
        void CloseHighScoreFile(void);
       t@@ -72,9 +72,9 @@ Player *GetNextShooter(Player *Play);
        void DropPrivileges(void);
        
        #ifdef GUI_SERVER
       -void GuiServerLoop(gboolean is_service);
       +void GuiServerLoop(struct CMDLINE *cmdline, gboolean is_service);
        #ifdef CYGWIN
       -void ServiceMain(void);
       +void ServiceMain(struct CMDLINE *cmdline);
        #endif
        #endif
        #ifndef CYGWIN
 (DIR) diff --git a/src/winmain.c b/src/winmain.c
       t@@ -225,6 +225,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
          int argc;
          gboolean is_service;
          gchar *modpath;
       +  struct CMDLINE *cmdline;
        
        #ifdef ENABLE_NLS
          gchar *winlocale;
       t@@ -275,35 +276,36 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
          while (split[argc] && split[argc][0])
            argc++;
        
       -  SoundInit();
       -  GeneralStartup(argc, split);
       +  cmdline = GeneralStartup(argc, split);
          OpenLog();
       -  if (WantVersion || WantHelp) {
       +  SoundInit();
       +  if (cmdline->version || cmdline->help) {
            WindowPrintStart();
            g_set_print_handler(WindowPrintFunc);
       -    HandleHelpTexts();
       +    HandleHelpTexts(cmdline->help);
            WindowPrintEnd();
        #ifdef NETWORKING
          } else if (is_service) {
            InitNetwork();
            Network = Server = TRUE;
            win32_init(hInstance, hPrevInstance, "mainicon");
       -    ServiceMain();
       +    ServiceMain(cmdline);
            StopNetworking();
        #endif
       -  } else if (WantConvert) {
       +  } else if (cmdline->convert) {
            WindowPrintStart();
            g_set_print_handler(WindowPrintFunc);
       -    ConvertHighScoreFile();
       +    ConvertHighScoreFile(cmdline->convertfile);
            WindowPrintEnd();
          } else {
            InitNetwork();
       -    if (Server) {
       +    if (cmdline->server) {
        #ifdef NETWORKING
        #ifdef GUI_SERVER
       +      Server = TRUE;
              g_log_set_handler(NULL, G_LOG_LEVEL_CRITICAL, LogMessage, NULL);
              win32_init(hInstance, hPrevInstance, "mainicon");
       -      GuiServerLoop(FALSE);
       +      GuiServerLoop(cmdline, FALSE);
        #else
              AllocConsole();
              SetConsoleTitle(_("dopewars server"));
       t@@ -312,7 +314,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                                G_LOG_LEVEL_WARNING, ServerLogMessage, NULL);
              g_set_print_handler(ServerPrintFunc);
              newterm(NULL, NULL, NULL);
       -      ServerLoop();
       +      ServerLoop(cmdline);
        #endif /* GUI_SERVER */
        #else
              WindowPrintStart();
       t@@ -323,7 +325,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                        "configure script.\n"));
              WindowPrintEnd();
        #endif /* NETWORKING */
       -    } else if (AIPlayer) {
       +    } else if (cmdline->ai) {
              AllocConsole();
        
              /* Title of the Windows window used for AI player output */
       t@@ -333,23 +335,23 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                                LogMask() | G_LOG_LEVEL_MESSAGE |
                                G_LOG_LEVEL_WARNING, ServerLogMessage, NULL);
              g_set_print_handler(ServerPrintFunc);
       -      AIPlayerLoop();
       +      AIPlayerLoop(cmdline);
            } else {
       -      switch (WantedClient) {
       +      switch (cmdline->client) {
              case CLIENT_AUTO:
       -        if (!GtkLoop(hInstance, hPrevInstance, TRUE)) {
       +        if (!GtkLoop(hInstance, hPrevInstance, cmdline, TRUE)) {
                  AllocConsole();
                  SetConsoleTitle(_("dopewars"));
       -          CursesLoop();
       +          CursesLoop(cmdline);
                }
                break;
              case CLIENT_WINDOW:
       -        GtkLoop(hInstance, hPrevInstance, FALSE);
       +        GtkLoop(hInstance, hPrevInstance, cmdline, FALSE);
                break;
              case CLIENT_CURSES:
                AllocConsole();
                SetConsoleTitle(_("dopewars"));
       -        CursesLoop();
       +        CursesLoop(cmdline);
                break;
              }
            }
       t@@ -357,13 +359,13 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
            StopNetworking();
        #endif
          }
       +  FreeCmdLine(cmdline);
          CloseLog();
          LogFileEnd();
          g_strfreev(split);
          CloseHighScoreFile();
          g_free(PidFile);
          g_free(Log.File);
       -  g_free(ConvertFile);
          SoundClose();
          return 0;
        }