tWindows installer now upgrades properly; Windows system tray icon can be controlled via. MinToSysTray config variable; Unix server can now be configured while running via. "dopewars -A" - 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 c77672f5f19dc6838e0f010339fa43dbab051ff3
(DIR) parent 8f75f1bd80b636b71b665bf2b93d10c5adcdd511
(HTM) Author: Ben Webb <ben@salilab.org>
Date: Sun, 11 Nov 2001 19:20:30 +0000
Windows installer now upgrades properly; Windows system tray icon can be
controlled via. MinToSysTray config variable; Unix server can now be
configured while running via. "dopewars -A"
Diffstat:
M ChangeLog | 5 ++++-
M TODO | 7 ++++---
M doc/configfile.html | 9 ++++++++-
M po/POTFILES.in | 1 +
M src/Makefile.am | 2 +-
M src/Makefile.in | 21 ++++++++++++---------
A src/admin.c | 104 +++++++++++++++++++++++++++++++
A src/admin.h | 35 +++++++++++++++++++++++++++++++
M src/dopewars.c | 48 +++++++++++++++++++++----------
M src/dopewars.h | 6 +++++-
M src/serverside.c | 113 +++++++++++++++++++------------
M src/serverside.h | 1 -
M win32/filelist | 5 +++++
M win32/makeinstall.c | 14 +++++++++-----
M win32/setup.c | 240 +++++++++++++++++++++++++++----
M win32/uninstall.c | 249 ++-----------------------------
M win32/util.c | 247 +++++++++++++++++++++++++++++++
M win32/util.h | 7 +++++++
18 files changed, 765 insertions(+), 349 deletions(-)
---
(DIR) diff --git a/ChangeLog b/ChangeLog
t@@ -1,4 +1,7 @@
cvs
+ - Fatal bug when visiting the bank (under Win2000/XP) fixed
+ - Windows installer should now upgrade old versions properly
+ - Windows server can now be run as an NT Service
- Currency can now be configured with Currency.Symbol and Currency.Prefix
- Windows client windows cannot now be made unreadably small
- Bank/loan shark dialog now warns on entering negative prices
t@@ -7,7 +10,7 @@ cvs
- Documentation on the client-server protocol added
- Windows graphical server can be minimized to the System Tray
- Keyboard shortcuts for menu items in Windows client
- - Default buttons for Windows client, bank bug (hopefully) fixed
+ - Default buttons (ENTER -> "OK") for Windows client
- RPM build/make install can now be run as non-superuser
- Code cleanups
(DIR) diff --git a/TODO b/TODO
t@@ -1,7 +1,8 @@
-- Make Windows installer deal with old installed versions properly
-- Make server run as an NT Service
+- 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)
- Configuration file editor thingy in the client?
-- Make minimize-to-systray code a) more robust and b) configurable
- GSS_API SOCKS support?
- Fix problem with dialogs popping up while menus are open
- Increase difficulty of escaping from another player - impose penalty on
(DIR) diff --git a/doc/configfile.html b/doc/configfile.html
t@@ -141,6 +141,13 @@ mode, not connected to a server) to use the file <i>/var/lib/dopewars.sco</i>
to store high scores. This can be overridden with the -f
<a href="commandline.html#hiscore">command line option</a>.</dd>
+<dt><b>MinToSysTray=<i>TRUE</i></b></dt>
+<dd>Rather than behaving as a normal window, the dopewars server window adds
+an icon to the Windows System Tray, and, when the window is minimized, it
+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>
t@@ -597,6 +604,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>28-10-2001</b></p>
+<p>Last update: <b>20-11-2001</b></p>
</body>
</html>
(DIR) diff --git a/po/POTFILES.in b/po/POTFILES.in
t@@ -10,4 +10,5 @@ src/serverside.c
src/error.c
src/message.c
src/network.c
+src/admin.c
src/AIPlayer.c
(DIR) diff --git a/src/Makefile.am b/src/Makefile.am
t@@ -1,5 +1,5 @@
bin_PROGRAMS = dopewars
-dopewars_SOURCES = AIPlayer.c curses_client.c dopeos.c dopewars.c \
+dopewars_SOURCES = admin.c AIPlayer.c curses_client.c dopeos.c dopewars.c \
error.c gtk_client.c message.c network.c serverside.c \
tstring.c winmain.c @GTKPORT_C@
dopewars_DEPENDENCIES = @INTLLIBS@ @GTKPORT_O@ @WNDRES@
(DIR) diff --git a/src/Makefile.in b/src/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,9 @@ WNDRES = @WNDRES@
localedir = @localedir@
bin_PROGRAMS = dopewars
-dopewars_SOURCES = AIPlayer.c curses_client.c dopeos.c dopewars.c error.c gtk_client.c message.c network.c serverside.c tstring.c winmain.c @GTKPORT_C@
+dopewars_SOURCES = admin.c AIPlayer.c curses_client.c dopeos.c dopewars.c \
+ error.c gtk_client.c message.c network.c serverside.c \
+ tstring.c winmain.c @GTKPORT_C@
dopewars_DEPENDENCIES = @INTLLIBS@ @GTKPORT_O@ @WNDRES@
INCLUDES = @GTK_CFLAGS@ -I.. -I.
t@@ -114,9 +116,9 @@ PROGRAMS = $(bin_PROGRAMS)
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
-dopewars_OBJECTS = AIPlayer.o curses_client.o dopeos.o dopewars.o \
-error.o gtk_client.o message.o network.o serverside.o tstring.o \
-winmain.o
+dopewars_OBJECTS = admin.o AIPlayer.o curses_client.o dopeos.o \
+dopewars.o error.o gtk_client.o message.o network.o serverside.o \
+tstring.o winmain.o
dopewars_LDADD = $(LDADD)
dopewars_LDFLAGS =
CFLAGS = @CFLAGS@
t@@ -130,9 +132,10 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = gtar
GZIP_ENV = --best
-DEP_FILES = .deps/AIPlayer.P .deps/curses_client.P .deps/dopeos.P \
-.deps/dopewars.P .deps/error.P .deps/gtk_client.P .deps/message.P \
-.deps/network.P .deps/serverside.P .deps/tstring.P .deps/winmain.P
+DEP_FILES = .deps/AIPlayer.P .deps/admin.P .deps/curses_client.P \
+.deps/dopeos.P .deps/dopewars.P .deps/error.P .deps/gtk_client.P \
+.deps/message.P .deps/network.P .deps/serverside.P .deps/tstring.P \
+.deps/winmain.P
SOURCES = $(dopewars_SOURCES)
OBJECTS = $(dopewars_OBJECTS)
(DIR) diff --git a/src/admin.c b/src/admin.c
t@@ -0,0 +1,104 @@
+/* admin.c Dopewars server administration */
+/* Copyright (C) 1998-2001 Ben Webb */
+/* Email: ben@bellatrix.pcl.ox.ac.uk */
+/* WWW: http://dopewars.sourceforge.net/ */
+
+/* This program is free software; you can redistribute it and/or */
+/* modify it under the terms of the GNU General Public License */
+/* as published by the Free Software Foundation; either version 2 */
+/* of the License, or (at your option) any later version. */
+
+/* This program is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
+/* GNU General Public License for more details. */
+
+/* You should have received a copy of the GNU General Public License */
+/* along with this program; if not, write to the Free Software */
+/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, */
+/* MA 02111-1307, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef CYGWIN
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <stdio.h>
+#include <glib.h>
+
+#include "network.h"
+
+static int OpenSocket(void) {
+ struct sockaddr_un addr;
+ int sock;
+
+ g_print("Attempting to connect to local dopewars server via. Unix domain\n"
+ "socket /tmp/.dopewars/socket...\n");
+ sock = socket(PF_UNIX,SOCK_STREAM,0);
+ if (sock==-1) { perror("socket"); exit(1); }
+
+ addr.sun_family = AF_UNIX;
+ strncpy(addr.sun_path,"/tmp/.dopewars/socket",sizeof(addr.sun_path));
+ addr.sun_path[sizeof(addr.sun_path)-1]='\0';
+
+ if (connect(sock,(struct sockaddr *)&addr,sizeof(struct sockaddr_un))==-1) {
+ perror("connect"); exit(1);
+ }
+
+ g_print("Connection established.\n\n");
+
+ return sock;
+}
+
+void AdminServer(void) {
+ int sock,topsock;
+ NetworkBuffer *netbuf;
+ fd_set readfds,writefds,errorfds;
+ gchar *msg,inbuf[200];
+ gboolean doneOK;
+
+ sock=OpenSocket();
+ netbuf = g_new(NetworkBuffer,1);
+ InitNetworkBuffer(netbuf,'\n','\r',NULL);
+ BindNetworkBufferToSocket(netbuf,sock);
+
+ while(1) {
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+ FD_ZERO(&errorfds);
+
+ FD_SET(0,&readfds);
+ topsock=1;
+ SetSelectForNetworkBuffer(netbuf,&readfds,&writefds,&errorfds,&topsock);
+
+ if (select(topsock,&readfds,&writefds,&errorfds,NULL)==-1) {
+ if (errno==EINTR) continue;
+ else perror("select"); break;
+ }
+
+ if (FD_ISSET(0,&readfds)) {
+ if (fgets(inbuf,sizeof(inbuf),stdin)) {
+ inbuf[sizeof(inbuf)-1]='\0';
+ if (strlen(inbuf)>0) {
+ if (inbuf[strlen(inbuf)-1]=='\n') inbuf[strlen(inbuf)-1]='\0';
+ QueueMessageForSend(netbuf,inbuf);
+ }
+ } else break;
+ }
+
+ if (RespondToSelect(netbuf,&readfds,&writefds,&errorfds,&doneOK)) {
+ while((msg=GetWaitingMessage(netbuf))!=NULL) {
+ g_print("%s\n",msg); g_free(msg);
+ }
+ }
+ if (!doneOK) break;
+ }
+ ShutdownNetworkBuffer(netbuf);
+ g_free(netbuf);
+ g_print("Connection closed\n");
+}
+#endif
(DIR) diff --git a/src/admin.h b/src/admin.h
t@@ -0,0 +1,35 @@
+/* admin.h Header file for dopewars server administration */
+/* Copyright (C) 1998-2001 Ben Webb */
+/* Email: ben@bellatrix.pcl.ox.ac.uk */
+/* WWW: http://dopewars.sourceforge.net/ */
+
+/* This program is free software; you can redistribute it and/or */
+/* modify it under the terms of the GNU General Public License */
+/* as published by the Free Software Foundation; either version 2 */
+/* of the License, or (at your option) any later version. */
+
+/* This program is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
+/* GNU General Public License for more details. */
+
+/* You should have received a copy of the GNU General Public License */
+/* along with this program; if not, write to the Free Software */
+/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, */
+/* MA 02111-1307, USA. */
+
+
+#ifndef __ADMIN_H__
+#define __ADMIN_H__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef CYGWIN
+
+void AdminServer(void);
+
+#endif /* CYGWIN */
+
+#endif
(DIR) diff --git a/src/dopewars.c b/src/dopewars.c
t@@ -41,6 +41,7 @@
#include <signal.h>
#include <glib.h>
#include <stdarg.h>
+#include "admin.h"
#include "curses_client.h"
#include "dopeos.h"
#include "gtk_client.h"
t@@ -69,7 +70,13 @@ FILE *logfp;
unsigned Port=7902;
gboolean Sanitized,ConfigVerbose,DrugValue;
gchar *HiScoreFile=NULL,*ServerName=NULL,*Pager=NULL,*ConvertFile=NULL;
-gboolean WantHelp,WantVersion,WantAntique,WantColour,WantNetwork,WantConvert;
+gboolean WantHelp,WantVersion,WantAntique,WantColour,WantNetwork,
+ WantConvert,WantAdmin;
+
+#ifdef CYGWIN
+gboolean MinToSysTray=TRUE;
+#endif
+
ClientType WantedClient;
int NumLocation=0,NumGun=0,NumCop=0,NumDrug=0,NumSubway=0,
NumPlaying=0,NumStoppedTo=0;
t@@ -259,6 +266,11 @@ struct GLOBALS Globals[] = {
"MetaServer.Proxy.Password",
N_("Password for HTTP Basic proxy authentication"),
NULL,NULL,0,"",NULL,NULL },
+#endif /* NETWORKING */
+#ifdef CYGWIN
+ { NULL,&MinToSysTray,NULL,NULL,NULL,"MinToSysTray",
+ N_("If TRUE, the server minimizes to the System Tray"),
+ 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 },
t@@ -1433,7 +1445,8 @@ void ReadConfigFile(char *FileName) {
while (!g_scanner_eof(scanner)) if (!ParseNextConfig(scanner,FALSE)) {
errors++;
g_scanner_error(scanner,
- _("Unable to process configuration file line"));
+ _("Unable to process configuration file line %d"),
+ g_scanner_cur_line(scanner));
}
g_scanner_destroy(scanner);
fclose(fp);
t@@ -1448,8 +1461,8 @@ _("Errors were encountered during the reading of the configuration file.\n"
"file \"dopewars-log.txt\" for further details."));
#else
g_warning(
-_("Errors were encountered during the reading of the configuration file.\n"
-"As a result, some settings may not work as expected. Please see the\n"
+_("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
}
t@@ -1796,7 +1809,7 @@ void SetupParameters() {
FirstClient=FirstServer=NULL;
Noone.Name=g_strdup("Noone");
WantColour=WantNetwork=TRUE;
- WantHelp=WantConvert=WantVersion=WantAntique=FALSE;
+ WantHelp=WantConvert=WantVersion=WantAntique=WantAdmin=FALSE;
WantedClient=CLIENT_AUTO;
Server=AIPlayer=Client=Network=FALSE;
t@@ -1891,16 +1904,16 @@ Drug dealing game based on \"Drug Wars\" by John E. Dell\n\
default %s/dopewars.sco is used)\n\
-o, --hostname=ADDR specify a hostname where the server for multiplayer\n\
dopewars can be found\n\
- -s, --public-server run in server mode (note: for a \"non-interactive\"\n\
- server, simply run as\n\
- dopewars -s < /dev/null >> logfile & )\n\
+ -s, --public-server run in server mode (note: see the -A option for\n\
+ configuring a server once it\'s running)\n\
-S, --private-server run a \"private\" server (do not notify the metaserver)\n\
-p, --port=PORT specify the network port to use (default: 7902)\n\
- -g, --config-file=FILE specify the pathname of a dopewars configuration file.\n\
- This file is read immediately when the -g option\n\
+ -g, --config-file=FILE specify the pathname of a dopewars configuration file;\n\
+ this file is read immediately when the -g option\n\
is encountered\n\
-r, --pidfile=FILE maintain pid file \"FILE\" while running the server\n\
-l, --logfile=FILE write log information to \"FILE\"\n\
+ -A, --admin connect to a locally-running server for administration\n\
-c, --ai-player create and run a computer player\n\
-w, --windowed-client force the use of a graphical (windowed)\n\
client (GTK+ or Win32)\n\
t@@ -1926,11 +1939,11 @@ Drug dealing game based on \"Drug Wars\" by John E. Dell\n\
(by default %s/dopewars.sco is used)\n\
-o addr specify a hostname where the server for multiplayer dopewars\n\
can be found\n\
- -s run in server mode (note: for a \"non-interactive\" server, simply\n\
- run as dopewars -s < /dev/null >> logfile & )\n\
+ -s run in server mode (note: see the -A option for configuring a\n\
+ server once it\'s running)\n\
-S run a \"private\" server (i.e. do not notify the metaserver)\n\
-p port specify the network port to use (default: 7902)\n\
- -g file specify the pathname of a dopewars configuration file. This file\n\
+ -g file specify the pathname of a dopewars configuration file; this file\n\
is read immediately when the -g option is encountered\n\
-r file maintain pid file \"file\" while running the server\n\
-l file write log information to \"file\"\n\
t@@ -1939,6 +1952,7 @@ Drug dealing game based on \"Drug Wars\" by John E. Dell\n\
-t force the use of a text-mode client (curses)\n\
(by default, a windowed client is used when possible)\n\
-C file convert an \"old format\" score file to the new format\n\
+ -A connect to a locally-running server for administration\n\
-h display this help information\n\
-v output version information and exit\n\n\
dopewars is Copyright (C) Ben Webb 1998-2001, and released under the GNU GPL\n\
t@@ -1948,7 +1962,7 @@ Report bugs to the author at ben@bellatrix.pcl.ox.ac.uk\n"),DATADIR);
void HandleCmdLine(int argc,char *argv[]) {
int c;
- static const gchar *options = "anbchvf:o:sSp:g:r:wtC:l:N";
+ static const gchar *options = "anbchvf:o:sSp:g:r:wtC:l:NA";
#ifdef HAVE_GETOPT_LONG
static const struct option long_options[] = {
{ "no-color", no_argument, NULL, 'b' },
t@@ -1967,6 +1981,7 @@ void HandleCmdLine(int argc,char *argv[]) {
{ "text-client", no_argument, NULL, 't' },
{ "convert", required_argument, NULL, 'C' },
{ "logfile", required_argument, NULL, 'l' },
+ { "admin", no_argument, NULL, 'A' },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'v' },
{ 0, 0, 0, 0 }
t@@ -1999,6 +2014,7 @@ void HandleCmdLine(int argc,char *argv[]) {
case 'w': WantedClient=CLIENT_WINDOW; break;
case 't': WantedClient=CLIENT_CURSES; break;
case 'C': AssignName(&ConvertFile,optarg); WantConvert=TRUE; break;
+ case 'A': WantAdmin=TRUE; break;
}
} while (c!=-1);
}
t@@ -2008,7 +2024,7 @@ int GeneralStartup(int argc,char *argv[]) {
/* score init.) - Returns 0 if OK, -1 if something failed. */
SetupParameters();
HandleCmdLine(argc,argv);
- if (!WantVersion && !WantHelp && !AIPlayer && !WantConvert) {
+ if (!WantVersion && !WantHelp && !AIPlayer && !WantConvert && !WantAdmin) {
return InitHighScoreFile();
}
return 0;
t@@ -2063,6 +2079,8 @@ int main(int argc,char *argv[]) {
if (GeneralStartup(argc,argv)==0) {
if (WantVersion || WantHelp) {
HandleHelpTexts();
+ } else if (WantAdmin) {
+ AdminServer();
} else if (WantConvert) {
ConvertHighScoreFile();
} else {
(DIR) diff --git a/src/dopewars.h b/src/dopewars.h
t@@ -155,7 +155,10 @@ extern gboolean Sanitized,ConfigVerbose,DrugValue;
extern int NumLocation,NumGun,NumCop,NumDrug,NumSubway,NumPlaying,NumStoppedTo;
extern gchar *HiScoreFile,*ServerName,*Pager,*ConvertFile;
extern gboolean WantHelp,WantVersion,WantAntique,WantColour,
- WantNetwork,WantConvert;
+ WantNetwork,WantConvert,WantAdmin;
+#ifdef CYGWIN
+extern gboolean MinToSysTray;
+#endif
extern ClientType WantedClient;
extern int LoanSharkLoc,BankLoc,GunShopLoc,RoughPubLoc;
extern int DrugSortMethod,FightTimeout,IdleTimeout,ConnectTimeout;
t@@ -393,4 +396,5 @@ void dopelog(int loglevel,const gchar *format,...);
GLogLevelFlags LogMask(void);
GString *GetLogString(GLogLevelFlags log_level,const gchar *message);
void RestoreConfig(void);
+void ScannerErrorHandler(GScanner *scanner,gchar *msg,gint error);
#endif
(DIR) diff --git a/src/serverside.c b/src/serverside.c
t@@ -598,10 +598,26 @@ void PrintHelpTo(FILE *fp) {
g_string_free(VarName,TRUE);
}
+static NetworkBuffer *reply_netbuf;
+static void ServerReply(const gchar *msg) {
+ int msglen;
+ gchar *msgcp;
+
+ if (reply_netbuf) {
+ msglen=strlen(msg);
+ while (msglen>0 && msg[msglen-1]=='\n') msglen--;
+ if (msglen>0) {
+ msgcp = g_strndup(msg,msglen);
+ QueueMessageForSend(reply_netbuf,msgcp);
+ g_free(msgcp);
+ }
+ } else g_print(msg);
+}
+
void ServerHelp(void) {
/* Displays a simple help screen listing the server commands and options */
int i;
-#if CYGWIN || GUI_SERVER
+//#if CYGWIN || GUI_SERVER
int Lines;
GString *VarName;
VarName=g_string_new("");
t@@ -616,14 +632,14 @@ void ServerHelp(void) {
}
g_print("%-26s\t%s\n",VarName->str,_(Globals[i].Help));
Lines++;
-#ifndef GUI_SERVER
+/*#ifndef GUI_SERVER
if (Lines%24==0) {
g_print(_("--More--")); bgetch(); g_print("\n");
}
-#endif
+endif*/
}
g_string_free(VarName,TRUE);
-#else
+/*#else
FILE *fp;
fp=popen(Pager,"w");
if (fp) {
t@@ -634,7 +650,7 @@ void ServerHelp(void) {
PrintHelpTo(stdout);
}
}
-#endif
+endif*/
}
#if NETWORKING
t@@ -706,6 +722,7 @@ static void StartServer(void) {
#endif
Scanner=g_scanner_new(&ScannerConfig);
+ Scanner->msg_handler=ScannerErrorHandler;
Scanner->input_name="(stdin)";
CreatePidFile();
t@@ -810,9 +827,23 @@ gboolean IsServerShutdown(void) {
return (WantQuit && !FirstServer && !MetaConn);
}
-void HandleServerCommand(char *string) {
+static GPrintFunc StartServerReply(NetworkBuffer *netbuf) {
+ reply_netbuf = netbuf;
+ if (netbuf) return g_set_print_handler(ServerReply);
+ else return NULL;
+}
+
+static void FinishServerReply(GPrintFunc oldprint) {
+ if (oldprint) g_set_print_handler(oldprint);
+}
+
+static void HandleServerCommand(char *string,NetworkBuffer *netbuf) {
GSList *list;
Player *tmp;
+ GPrintFunc oldprint;
+
+ oldprint = StartServerReply(netbuf);
+
g_scanner_input_text(Scanner,string,strlen(string));
if (!ParseNextConfig(Scanner,TRUE)) {
if (g_strcasecmp(string,"help")==0 || g_strcasecmp(string,"h")==0 ||
t@@ -827,27 +858,30 @@ void HandleServerCommand(char *string) {
g_print(_("Users currently logged on:-\n"));
for (list=FirstServer;list;list=g_slist_next(list)) {
tmp=(Player *)list->data;
- if (!IsCop(tmp)) g_print("%s\n",GetPlayerName(tmp));
+ if (!IsCop(tmp)) {
+ g_print("%s\n",GetPlayerName(tmp));
+ }
}
} else g_print(_("No users currently logged on!\n"));
} else if (g_strncasecmp(string,"push ",5)==0) {
tmp=GetPlayerByName(string+5,FirstServer);
if (tmp) {
- dopelog(0,_("Pushing %s"),GetPlayerName(tmp));
+ g_print(_("Pushing %s\n"),GetPlayerName(tmp));
SendServerMessage(NULL,C_NONE,C_PUSH,tmp,NULL);
- } else g_warning(_("No such user!"));
+ } else g_print(_("No such user!\n"));
} else if (g_strncasecmp(string,"kill ",5)==0) {
tmp=GetPlayerByName(string+5,FirstServer);
if (tmp) {
- dopelog(0,_("%s killed"),GetPlayerName(tmp));
+ g_print(_("%s killed\n"),GetPlayerName(tmp));
BroadcastToClients(C_NONE,C_KILL,GetPlayerName(tmp),tmp,
(Player *)FirstServer->data);
FirstServer=RemovePlayer(tmp,FirstServer);
- } else g_warning(_("No such user!"));
+ } else g_print(_("No such user!\n"));
} else {
- g_warning(_("Unknown command - try \"help\" for help..."));
+ g_print(_("Unknown command - try \"help\" for help...\n"));
}
}
+ FinishServerReply(oldprint);
}
Player *HandleNewConnection(void) {
t@@ -890,27 +924,15 @@ void RemovePlayerFromServer(Player *Play) {
}
#ifndef CYGWIN
-static gchar sockdir[] = "/tmp/.dopewars/";
-
-static gchar *GetLocalSocket(void) {
- return g_strdup_printf("%ssocket-%u",sockdir,Port);
-}
-
static void CloseLocalSocket(int localsock) {
- gchar *sockname;
-
if (localsock>=0) close(localsock);
-
- sockname=GetLocalSocket();
- unlink(sockname);
- rmdir(sockdir);
- g_free(sockname);
+ unlink("/tmp/.dopewars/socket");
+ rmdir("/tmp/.dopewars");
}
static int SetupLocalSocket(void) {
int sock;
struct sockaddr_un addr;
- gchar *sockname;
CloseLocalSocket(-1);
t@@ -919,20 +941,17 @@ static int SetupLocalSocket(void) {
SetBlocking(sock,FALSE);
- sockname=GetLocalSocket();
- mkdir(sockdir,S_IRUSR|S_IWUSR|S_IXUSR);
+ mkdir("/tmp/.dopewars",S_IRUSR|S_IWUSR|S_IXUSR);
addr.sun_family = AF_UNIX;
- strncpy(addr.sun_path,sockname,sizeof(addr.sun_path));
+ strncpy(addr.sun_path,"/tmp/.dopewars/socket",sizeof(addr.sun_path));
addr.sun_path[sizeof(addr.sun_path)-1]='\0';
bind(sock,(struct sockaddr *)&addr,sizeof(struct sockaddr_un));
- chmod(sockname,S_IRUSR|S_IWUSR);
+ chmod("/tmp/.dopewars/socket",S_IRUSR|S_IWUSR);
listen(sock,10);
-
- g_free(sockname);
return sock;
}
t@@ -945,11 +964,12 @@ void ServerLoop() {
GSList *list,*nextlist,*localconn=NULL;
fd_set readfs,writefs,errorfs;
int topsock;
+ GPrintFunc oldprint;
// gboolean InputClosed=FALSE;
struct timeval timeout;
int MinTimeout;
GString *LineBuf;
- gboolean EndOfLine,DoneOK;
+ gboolean /*EndOfLine,*/DoneOK;
gchar *buf;
#ifndef CYGWIN
int localsock;
t@@ -1039,9 +1059,12 @@ void ServerLoop() {
netbuf=g_new(NetworkBuffer,1);
InitNetworkBuffer(netbuf,'\n','\r',NULL);
BindNetworkBufferToSocket(netbuf,newlocal);
- SetBlocking(newlocal,FALSE);
localconn = g_slist_append(localconn,netbuf);
-g_print("New connection on Unix socket\n");
+ oldprint = StartServerReply(netbuf);
+ g_print(_("dopewars server version %s ready for admin commands; "
+ "try \"help\" for help"),VERSION);
+ FinishServerReply(oldprint);
+ dopelog(1,_("New admin connection"));
}
list=localconn;
while (list) {
t@@ -1051,13 +1074,13 @@ g_print("New connection on Unix socket\n");
if (netbuf) {
if (RespondToSelect(netbuf,&readfs,&writefs,&errorfs,&DoneOK)) {
while((buf=GetWaitingMessage(netbuf))!=NULL) {
- g_print("Unix message received: %s\n",buf);
- HandleServerCommand(buf);
+ dopelog(2,_("Admin command: %s"),buf);
+ HandleServerCommand(buf,netbuf);
g_free(buf);
}
}
if (!DoneOK) {
-g_print("Unix socket closed\n");
+ dopelog(1,_("Admin connection closed"));
localconn = g_slist_remove(localconn,netbuf);
ShutdownNetworkBuffer(netbuf);
g_free(netbuf);
t@@ -1198,7 +1221,7 @@ static void GuiDoCommand(GtkWidget *widget,gpointer data) {
gchar *text;
text=gtk_editable_get_chars(GTK_EDITABLE(widget),0,-1);
gtk_editable_delete_text(GTK_EDITABLE(widget),0,-1);
- HandleServerCommand(text);
+ HandleServerCommand(text,NULL);
g_free(text);
if (IsServerShutdown()) GuiQuitServer();
}
t@@ -1289,7 +1312,7 @@ static gint GuiRequestDelete(GtkWidget *widget,GdkEvent *event,gpointer data) {
GuiQuitServer();
} else {
TriedPoliteShutdown=TRUE;
- HandleServerCommand("quit");
+ HandleServerCommand("quit",NULL);
if (IsServerShutdown()) GuiQuitServer();
}
return TRUE; /* Never allow automatic deletion - we handle it manually */
t@@ -1297,6 +1320,7 @@ static gint GuiRequestDelete(GtkWidget *widget,GdkEvent *event,gpointer data) {
#ifdef CYGWIN
static HWND mainhwnd=NULL;
+static BOOL systray=FALSE;
static BOOL RegisterStatus(DWORD state) {
SERVICE_STATUS status;
t@@ -1367,7 +1391,7 @@ static LRESULT CALLBACK GuiServerWndProc(HWND hwnd,UINT msg,WPARAM wparam,
if ((UINT)lparam==WM_LBUTTONDOWN) ShowWindow(mainhwnd,SW_SHOW);
break;
case WM_SYSCOMMAND:
- if (wparam==SC_MINIMIZE) {
+ if (wparam==SC_MINIMIZE && systray) {
ShowWindow(mainhwnd,SW_HIDE); return TRUE;
}
break;
t@@ -1384,14 +1408,14 @@ static void SetupTaskBarIcon(GtkWidget *widget) {
if (!widget && !mainhwnd) return;
nid.hWnd = mainhwnd;
- if (widget) {
+ if (widget && MinToSysTray) {
nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
nid.uCallbackMessage = MYWM_TASKBAR;
nid.hIcon = mainIcon;
strcpy(nid.szTip,"dopewars server - running");
- Shell_NotifyIcon(NIM_ADD,&nid);
- SetCustomWndProc(GuiServerWndProc);
+ systray=Shell_NotifyIcon(NIM_ADD,&nid);
} else {
+ systray=FALSE;
Shell_NotifyIcon(NIM_DELETE,&nid);
}
}
t@@ -1445,6 +1469,7 @@ void GuiServerLoop(gboolean is_service) {
#ifdef CYGWIN
mainhwnd=window->hWnd;
SetupTaskBarIcon(window);
+ SetCustomWndProc(GuiServerWndProc);
if (is_service && !RegisterStatus(SERVICE_RUNNING)) {
dopelog(0,_("Failed to set NT Service status"));
return;
(DIR) diff --git a/src/serverside.h b/src/serverside.h
t@@ -35,7 +35,6 @@ void CleanUpServer(void);
void BreakHandle(int sig);
void ClientLeftServer(Player *Play);
void StopServer(void);
-void HandleServerCommand(char *string);
Player *HandleNewConnection(void);
void ServerLoop(void);
void HandleServerPlayer(Player *Play);
(DIR) diff --git a/win32/filelist b/win32/filelist
t@@ -41,6 +41,11 @@ uninstall.exe
dopewars-log.txt
dopewars.sco
+[keepfiles]
+dopewars-config.txt
+dopewars-log.txt
+dopewars.sco
+
[startmenudir]
dopewars-1.5.3
(DIR) diff --git a/win32/makeinstall.c b/win32/makeinstall.c
t@@ -51,23 +51,23 @@ char *read_line(HANDLE hin) {
InstData *ReadInstallData() {
HANDLE fin;
char *line,*line2,*line3,*line4;
- InstFiles *lastinst=NULL,*lastextra=NULL;
+ InstFiles *lastinst=NULL,*lastextra=NULL,*lastkeep=NULL;
InstLink *lastmenu=NULL,*lastdesktop=NULL;
InstData *idata;
int i;
enum {
- S_PRODUCT=0,S_INSTDIR,S_INSTALL,S_EXTRA,S_STARTMENUDIR,
+ S_PRODUCT=0,S_INSTDIR,S_INSTALL,S_EXTRA,S_KEEP,S_STARTMENUDIR,
S_STARTMENU,S_DESKTOP,S_NTSERVICE,
S_NONE
} section=S_NONE;
char *titles[S_NONE] = {
- "[product]","[instdir]", "[install]","[extrafiles]","[startmenudir]",
- "[startmenu]","[desktop]","[NT Service]"
+ "[product]","[instdir]", "[install]","[extrafiles]","[keepfiles]",
+ "[startmenudir]","[startmenu]","[desktop]","[NT Service]"
};
idata = bmalloc(sizeof(InstData));
idata->installdir = idata->startmenudir = NULL;
- idata->instfiles = idata->extrafiles = NULL;
+ idata->instfiles = idata->extrafiles = idata->keepfiles = NULL;
idata->startmenu = idata->desktop = NULL;
idata->service = NULL;
t@@ -104,6 +104,9 @@ printf("start menu dir = %s\n",line);
case S_EXTRA:
AddInstFiles(line,0,&lastextra,&idata->extrafiles);
break;
+ case S_KEEP:
+ AddInstFiles(line,0,&lastkeep,&idata->keepfiles);
+ break;
case S_STARTMENU:
line2=read_line(fin); line3=read_line(fin);
printf("start menu entry = %s/%s/%s\n",line,line2,line3);
t@@ -252,6 +255,7 @@ int main() {
WriteLinkList(fout,idata->desktop);
WriteServiceDetails(fout,idata->service);
+ WriteFileList(fout,idata->keepfiles);
CloseHandle(fout);
bfree(inbuf);
(DIR) diff --git a/win32/setup.c b/win32/setup.c
t@@ -39,6 +39,7 @@ InstData *idata;
HWND mainDlg[DL_NUM];
DialogType CurrentDialog;
HINSTANCE hInst=NULL;
+char *oldversion=NULL;
DWORD WINAPI DoInstall(LPVOID lpParam);
static void GetWinText(char **text,HWND hWnd);
t@@ -251,7 +252,7 @@ LPVOID GetResource(LPCTSTR resname,LPCTSTR restype) {
}
InstData *ReadInstData() {
- InstFiles *lastinst=NULL,*lastextra=NULL;
+ InstFiles *lastinst=NULL,*lastextra=NULL,*lastkeep=NULL;
InstLink *lastmenu=NULL,*lastdesktop=NULL;
char *instdata,*pt,*filename,*line2,*line3,*line4;
DWORD filesize;
t@@ -319,6 +320,15 @@ InstData *ReadInstData() {
line4=pt; pt += strlen(pt)+1;
AddServiceDetails(filename,line2,line3,line4,&idata->service);
}
+ while (1) {
+ filename=pt;
+ pt += strlen(pt)+1;
+ if (filename[0]) {
+ filesize=atol(pt);
+ pt += strlen(pt)+1;
+ AddInstFiles(filename,filesize,&lastkeep,&idata->keepfiles);
+ } else break;
+ }
return idata;
}
t@@ -359,12 +369,16 @@ char *GetFirstFile(InstFiles *filelist,DWORD totalsize) {
return outbuf;
}
-BOOL OpenNextOutput(HANDLE *fout,InstFiles *filelist,InstFiles **listpt,
- DWORD *fileleft,HANDLE logf) {
+BOOL OpenNextOutput(HANDLE *fout,InstFiles *filelist,InstFiles *keepfiles,
+ InstFiles **listpt,DWORD *fileleft,HANDLE logf,
+ BOOL *skipfile) {
char *filename,*sep;
bstr *str;
+ InstFiles *keeppt;
DWORD bytes_written;
+ *skipfile=FALSE;
+
if (*fout) CloseHandle(*fout);
*fout = INVALID_HANDLE_VALUE;
t@@ -392,20 +406,29 @@ BOOL OpenNextOutput(HANDLE *fout,InstFiles *filelist,InstFiles **listpt,
CreateWholeDirectory(filename);
*sep = '\\';
}
- *fout = CreateFile(filename,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL);
- *fileleft = (*listpt)->filesize;
- bstr_assign(str,"Installing file: ");
- bstr_append(str,filename);
- bstr_append(str," (size ");
- bstr_append_long(str,(*listpt)->filesize);
- bstr_append(str,")");
- SendDlgItemMessage(mainDlg[DL_DOINSTALL],ST_FILELIST,
- WM_SETTEXT,0,(LPARAM)str->text);
- if (*fout==INVALID_HANDLE_VALUE) {
- bstr_assign(str,"Cannot create file ");
+ keeppt = keepfiles;
+ while (keeppt && strcmp(keeppt->filename,filename)!=0) keeppt=keeppt->next;
+
+/* If the file is already installed (filesize!=0), then skip it */
+ if (keeppt && keeppt->filesize!=0) {
+ *fout = INVALID_HANDLE_VALUE+1; /* Make sure the handle is valid */
+ *skipfile = TRUE;
+ } else {
+ *fout = CreateFile(filename,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL);
+ bstr_assign(str,"Installing file: ");
bstr_append(str,filename);
- DisplayError(str->text,TRUE,FALSE);
+ bstr_append(str," (size ");
+ bstr_append_long(str,(*listpt)->filesize);
+ bstr_append(str,")");
+ SendDlgItemMessage(mainDlg[DL_DOINSTALL],ST_FILELIST,
+ WM_SETTEXT,0,(LPARAM)str->text);
+ if (*fout==INVALID_HANDLE_VALUE) {
+ bstr_assign(str,"Cannot create file ");
+ bstr_append(str,filename);
+ DisplayError(str->text,TRUE,FALSE);
+ }
}
+ *fileleft = (*listpt)->filesize;
}
bstr_free(str,TRUE);
t@@ -569,13 +592,123 @@ void SetupUninstall() {
bfree(startmenu);
}
+void StartRemoveOldVersion(char *oldversion,InstData *idata,
+ InstData **oldidata,HWND hwnd) {
+ InstData *old;
+ bstr *str;
+ char *oldidir,*startmenu,*desktop;
+ HANDLE fin;
+
+ *oldidata=NULL;
+
+ if (!oldversion) return;
+
+ oldidir = GetInstallDir(oldversion);
+
+ if (!SetCurrentDirectory(oldidir)) {
+ str=bstr_new();
+ bstr_assign(str,"Could not access old version's install directory ");
+ bstr_append(str,oldidir);
+ DisplayError(str->text,TRUE,TRUE);
+ }
+
+ fin = CreateFile("install.log",GENERIC_READ,0,NULL,OPEN_EXISTING,0,NULL);
+
+ if (fin) {
+ old = ReadOldInstData(fin,oldversion,oldidir);
+ CloseHandle(fin);
+ DeleteFile("install.log");
+
+ RemoveService(old->service);
+ DeleteFileList(old->instfiles,hwnd,idata->keepfiles);
+ DeleteFileList(old->extrafiles,hwnd,idata->keepfiles);
+
+ startmenu = GetStartMenuDir(old);
+ desktop = GetDesktopDir();
+ DeleteLinkList(startmenu,old->startmenu,hwnd);
+ DeleteLinkList(desktop,old->desktop,hwnd);
+
+ RemoveUninstall(startmenu,oldversion,FALSE);
+
+ bfree(startmenu); bfree(desktop);
+ *oldidata = old;
+ }
+}
+
+void FinishRemoveOldVersion(char *oldversion,InstData *idata,
+ InstData *oldidata) {
+ InstFiles *keeppt;
+ bstr *str;
+ char *desktop,*startmenu;
+ if (!oldidata) return;
+
+ desktop = GetDesktopDir();
+
+ str = bstr_new();
+/* If we're installing into a different directory, move config. files etc.
+ from the old directory to the new one */
+ if (strcmp(oldidata->installdir,idata->installdir)!=0 &&
+ SetCurrentDirectory(oldidata->installdir)) {
+ for (keeppt = idata->keepfiles;keeppt;keeppt=keeppt->next) {
+ if (keeppt->filesize!=0) {
+ bstr_assign(str,idata->installdir);
+ bstr_appendpath(str,keeppt->filename);
+ if (CopyFile(keeppt->filename,str->text,FALSE)) {
+ DeleteFile(keeppt->filename);
+ }
+ }
+ }
+ SetCurrentDirectory(desktop); /* Make sure we're not in the install dir */
+ if (!RemoveWholeDirectory(oldidata->installdir)) {
+ bstr_assign(str,"Could not remove old install directory:\n");
+ bstr_append(str,oldidata->installdir);
+ bstr_append(str,"\nYou may wish to manually remove it later.");
+ DisplayError(str->text,FALSE,FALSE);
+ }
+ }
+
+ if (strcmp(idata->startmenudir,oldidata->startmenudir)!=0) {
+ SetCurrentDirectory(desktop); /* Make sure we're not in the menu dir */
+ startmenu = GetStartMenuDir(oldidata);
+ if (!RemoveWholeDirectory(startmenu)) {
+ bstr_assign(str,"Could not remove old Start Menu directory:\n");
+ bstr_append(str,startmenu);
+ bstr_append(str,"\nYou may wish to manually remove it later.");
+ DisplayError(str->text,FALSE,FALSE);
+ }
+ bfree(startmenu);
+ }
+
+/* Remove the old registry key */
+ bstr_assign(str,UninstallKey);
+ bstr_appendpath(str,oldversion);
+ RegDeleteKey(HKEY_LOCAL_MACHINE,str->text);
+
+ bfree(desktop);
+ bstr_free(str,TRUE);
+
+ FreeInstData(oldidata,TRUE);
+ oldversion=NULL; /* This is freed by FreeInstData */
+}
+
DWORD WINAPI DoInstall(LPVOID lpParam) {
- HANDLE fout,logf;
+ HANDLE fout,logf,fin;
DWORD bytes_written,fileleft;
+ BOOL skipfile;
char *inbuf,*outbuf;
int status,count;
z_stream z;
InstFiles *listpt;
+ InstData *oldidata;
+
+/* Steal the filesize attribute to mark that these files are not
+ already installed */
+ for (listpt=idata->keepfiles;listpt;listpt=listpt->next) {
+ listpt->filesize=0;
+ }
+
+ StartRemoveOldVersion(oldversion,idata,&oldidata,
+ GetDlgItem(mainDlg[DL_DOINSTALL],ST_FILELIST));
inbuf = GetResource(MAKEINTRESOURCE(1),"INSTFILE");
if (!inbuf) return 0;
t@@ -586,6 +719,16 @@ DWORD WINAPI DoInstall(LPVOID lpParam) {
DisplayError("Cannot access install directory",TRUE,TRUE);
}
+/* Check for already-installed files */
+ for (listpt=idata->keepfiles;listpt;listpt=listpt->next) {
+ fin = CreateFile(listpt->filename,GENERIC_READ,0,NULL,OPEN_EXISTING,
+ 0,NULL);
+ if (fin != INVALID_HANDLE_VALUE) {
+ CloseHandle(fin);
+ listpt->filesize=1;
+ }
+ }
+
logf = CreateFile("install.log",GENERIC_WRITE,0,NULL,
CREATE_ALWAYS,0,NULL);
t@@ -596,7 +739,8 @@ DWORD WINAPI DoInstall(LPVOID lpParam) {
fout = INVALID_HANDLE_VALUE;
listpt=NULL;
- OpenNextOutput(&fout,idata->instfiles,&listpt,&fileleft,logf);
+ OpenNextOutput(&fout,idata->instfiles,idata->keepfiles,
+ &listpt,&fileleft,logf,&skipfile);
outbuf = bmalloc(BUFFER_SIZE);
t@@ -616,17 +760,18 @@ DWORD WINAPI DoInstall(LPVOID lpParam) {
count = BUFFER_SIZE - z.avail_out;
z.next_out = outbuf;
while (count >= fileleft) {
- if (fileleft &&
+ if (fileleft && !skipfile &&
!WriteFile(fout,z.next_out,fileleft,&bytes_written,NULL)) {
printf("Write error\n");
}
count-=fileleft;
z.next_out+=fileleft;
- if (!OpenNextOutput(&fout,idata->instfiles,&listpt,
- &fileleft,logf)) break;
+ if (!OpenNextOutput(&fout,idata->instfiles,idata->keepfiles,
+ &listpt,&fileleft,logf,&skipfile)) break;
}
if (fout==INVALID_HANDLE_VALUE) break;
- if (count && !WriteFile(fout,z.next_out,count,&bytes_written,NULL)) {
+ if (count && !skipfile &&
+ !WriteFile(fout,z.next_out,count,&bytes_written,NULL)) {
printf("Write error\n");
}
fileleft-=count;
t@@ -637,7 +782,7 @@ DWORD WINAPI DoInstall(LPVOID lpParam) {
}
inflateEnd(&z);
- CloseHandle(fout);
+ if (!skipfile) CloseHandle(fout);
outbuf[0]='\0';
if (!WriteFile(logf,outbuf,1,&bytes_written,NULL)) {
t@@ -647,6 +792,8 @@ DWORD WINAPI DoInstall(LPVOID lpParam) {
WriteFileList(logf,idata->extrafiles);
+ FinishRemoveOldVersion(oldversion,idata,oldidata);
+
InstallService(idata);
CoInitialize(NULL);
t@@ -699,7 +846,11 @@ void FillFolderList(void) {
}
BOOL CheckExistingInstall(InstData *idata) {
- bstr *str,*subkey;
+ bstr *str;
+ char *sep,*prodname,*prodversion;
+ char *subkey;
+ int sublen;
+ DWORD sublencp;
HKEY key;
DWORD ind;
FILETIME ftime;
t@@ -708,6 +859,9 @@ BOOL CheckExistingInstall(InstData *idata) {
str=bstr_new();
bstr_assign(str,UninstallKey);
bstr_appendpath(str,idata->product);
+
+/* Split product into name and version */
+ sep = strrchr(idata->product,'-');
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,str->text,0,KEY_READ,&key)
==ERROR_SUCCESS) {
t@@ -715,15 +869,45 @@ BOOL CheckExistingInstall(InstData *idata) {
if (MessageBox(NULL,"This program appears to already be installed.\n"
"Are you sure you want to go ahead and install it anyway?",
idata->product,MB_YESNO)==IDNO) retval=FALSE;
- } else {
-// TODO: Check for old versions to upgrade
+ } else if (sep) {
+ *sep='\0';
+ prodversion = sep+1;
+ prodname = bstrdup(idata->product);
+ *sep='-';
+ sublencp=sublen=strlen(idata->product)+30;
+ subkey = bmalloc(sublen);
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,UninstallKey,0,KEY_READ,&key)
==ERROR_SUCCESS) {
-/* for (ind=0;RegEnumKeyEx(key,ind,subkey,subkey->len,
- NULL,NULL,NULL,&ftime)==ERROR_SUCCESS;ind++) {
- }*/
+ ind=0;
+ while (RegEnumKeyEx(key,ind++,subkey,&sublencp,
+ NULL,NULL,NULL,&ftime)==ERROR_SUCCESS) {
+ sublencp=sublen;
+ sep=strrchr(subkey,'-');
+ if (sep) {
+ *sep='\0';
+ if (strcmp(subkey,prodname)==0) {
+ bstr_assign(str,"You are trying to install ");
+ bstr_append(str,idata->product);
+ bstr_append(str,".\nHowever, version ");
+ bstr_append(str,sep+1);
+ bstr_append(str," appears to already be installed.\n"
+ "Do you want to replace the existing version with "
+ "this one?\n(If you answer \"No\", and continue, "
+ "both versions will be installed.)");
+ if (MessageBox(NULL,str->text,"Existing version",MB_YESNO)==IDYES) {
+ *sep='-';
+ oldversion=bstrdup(subkey);
+ }
+ break;
+ }
+ }
+ }
+ RegCloseKey(key);
}
+ bfree(prodname);
+ bfree(subkey);
}
+ bstr_free(str,TRUE);
return retval;
}
(DIR) diff --git a/win32/uninstall.c b/win32/uninstall.c
t@@ -30,123 +30,6 @@ HINSTANCE hInst;
HWND mainDlg;
char *product;
-void RemoveService(NTService *service) {
- SC_HANDLE scManager,scService;
- SERVICE_STATUS status;
-
- if (!service) return;
-
- scManager = OpenSCManager(NULL,NULL,GENERIC_READ);
-
- if (!scManager) {
- DisplayError("Cannot connect to service manager",TRUE,FALSE);
- return;
- }
-
- scService = OpenService(scManager,service->name,DELETE|SERVICE_STOP);
- if (!scService) {
- DisplayError("Cannot open service",TRUE,FALSE);
- } else {
- if (!ControlService(scService,SERVICE_CONTROL_STOP,&status) &&
- GetLastError()!=ERROR_SERVICE_NOT_ACTIVE) {
- DisplayError("Cannot stop service",TRUE,FALSE);
- }
- if (!DeleteService(scService)) {
- DisplayError("Cannot delete service",TRUE,FALSE);
- }
- CloseServiceHandle(scService);
- }
-
- CloseServiceHandle(scManager);
-}
-
-char *read_line0(HANDLE hin) {
- char *buf;
- int bufsize=32,strind=0;
- DWORD bytes_read;
- buf = bmalloc(bufsize);
-
- while (1) {
- if (!ReadFile(hin,&buf[strind],1,&bytes_read,NULL)) {
- printf("Read error\n"); break;
- }
- if (bytes_read==0) { buf[strind]='\0'; break; }
- else if (buf[strind]=='\0') break;
- else {
- strind++;
- if (strind>=bufsize) {
- bufsize*=2;
- buf = brealloc(buf,bufsize);
- }
- }
- }
- if (strind==0) { bfree(buf); return NULL; }
- else return buf;
-}
-
-InstLink *ReadLinkList(HANDLE fin) {
- InstLink *first=NULL,*listpt=NULL,*newpt;
- char *linkfile,*origfile,*args;
-
- while (1) {
- linkfile=read_line0(fin);
- if (!linkfile) break;
- origfile=read_line0(fin);
- args=read_line0(fin);
- if (!origfile) DisplayError("Corrupt install.log",FALSE,TRUE);
- newpt = bmalloc(sizeof(InstLink));
- if (listpt) listpt->next = newpt;
- else first = newpt;
- listpt = newpt;
- newpt->next=NULL;
- newpt->linkfile=linkfile;
- newpt->origfile=origfile;
- newpt->args=args;
- }
- return first;
-}
-
-NTService *ReadServiceDetails(HANDLE fin) {
- NTService *service=NULL;
- char *name,*disp,*desc,*exe;
-
- name = read_line0(fin);
- if (name) {
- disp = read_line0(fin);
- desc = read_line0(fin);
- exe = read_line0(fin);
- if (!disp || !desc || !exe) {
- DisplayError("Corrupt install.log",FALSE,TRUE);
- } else {
- AddServiceDetails(name,disp,desc,exe,&service);
- }
- }
-
- return service;
-}
-
-InstFiles *ReadFileList(HANDLE fin) {
- InstFiles *first=NULL,*listpt=NULL,*newpt;
- char *filename,*filesize;
-
- while (1) {
- filename=read_line0(fin);
- if (!filename) break;
- filesize=read_line0(fin);
- if (!filesize) DisplayError("Corrupt install.log",FALSE,TRUE);
- newpt = bmalloc(sizeof(InstFiles));
- if (listpt) listpt->next = newpt;
- else first = newpt;
- listpt = newpt;
-
- newpt->next=NULL;
- newpt->filename=filename;
- newpt->filesize=atol(filesize);
- bfree(filesize);
- }
- return first;
-}
-
char *GetProduct(void) {
char *product;
product = strrchr(GetCommandLine(),' ');
t@@ -157,125 +40,10 @@ char *GetProduct(void) {
}
}
-char *GetInstallDir(char *product) {
- HKEY key;
- bstr *str;
- DWORD keytype,keylen;
- char *installdir;
-
- str=bstr_new();
- bstr_assign(str,UninstallKey);
- bstr_appendpath(str,product);
- if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,str->text,0,
- KEY_ALL_ACCESS,&key)!=ERROR_SUCCESS) {
- DisplayError("Could not open registry",FALSE,TRUE);
- }
-
- if (RegQueryValueEx(key,"InstallDirectory",NULL,
- &keytype,NULL,&keylen)!=ERROR_SUCCESS ||
- keytype!=REG_SZ) {
- DisplayError("Could not query registry key",FALSE,TRUE);
- }
-
- installdir = bmalloc(keylen);
- if (RegQueryValueEx(key,"InstallDirectory",NULL,
- &keytype,installdir,&keylen)!=ERROR_SUCCESS) {
- DisplayError("Could not get registry key value",FALSE,TRUE);
- }
-
- bstr_free(str,TRUE);
- return installdir;
-}
-
-InstData *ReadInstData(HANDLE fin,char *product,char *installdir) {
- InstData *idata;
-
- idata=bmalloc(sizeof(InstData));
-
- idata->product=product;
- idata->installdir=installdir;
- idata->startmenudir=read_line0(fin);
-
- idata->instfiles = ReadFileList(fin);
- idata->extrafiles = ReadFileList(fin);
-
- idata->startmenu = ReadLinkList(fin);
- idata->desktop = ReadLinkList(fin);
-
- idata->service = ReadServiceDetails(fin);
- return idata;
-}
-
-void DeleteFileList(InstFiles *listpt) {
- bstr *str;
- char *sep;
-
- str=bstr_new();
- for (;listpt;listpt=listpt->next) {
- bstr_assign(str,"Deleting file: ");
- bstr_append(str,listpt->filename);
- SendDlgItemMessage(mainDlg,ST_DELSTAT,WM_SETTEXT,0,(LPARAM)str->text);
- DeleteFile(listpt->filename);
- sep = strrchr(listpt->filename,'\\');
- if (sep) {
- *sep = '\0';
- RemoveWholeDirectory(listpt->filename);
- *sep = '\\';
- }
- }
- bstr_free(str,TRUE);
-}
-
-void DeleteLinkList(char *dir,InstLink *listpt) {
- bstr *str;
- str=bstr_new();
- if (SetCurrentDirectory(dir)) {
- for (;listpt;listpt=listpt->next) {
- bstr_assign(str,"Deleting shortcut: ");
- bstr_append(str,listpt->linkfile);
- SendDlgItemMessage(mainDlg,ST_DELSTAT,WM_SETTEXT,0,(LPARAM)str->text);
- DeleteFile(listpt->linkfile);
- }
- } else {
- bstr_assign(str,"Could not find shortcut directory ");
- bstr_append(str,dir);
- DisplayError(str->text,TRUE,FALSE);
- }
- bstr_free(str,TRUE);
-}
-
-void RemoveUninstall(char *startmenu,char *product) {
- bstr *inipath,*uninstpath,*uninstlink;
-
- inipath=bstr_new();
- uninstpath=bstr_new();
- uninstlink=bstr_new();
-
- bstr_assign(uninstlink,startmenu);
- bstr_appendpath(uninstlink,"Uninstall ");
- bstr_append(uninstlink,product);
- bstr_append(uninstlink,".LNK");
- DeleteFile(uninstlink->text);
-
- bstr_assign_windir(inipath);
- bstr_assign(uninstpath,inipath->text);
-
- bstr_appendpath(inipath,"wininit.ini");
- bstr_appendpath(uninstpath,UninstallEXE);
-
- if (!WritePrivateProfileString("Renane","NUL",uninstpath->text,
- inipath->text)) {
- DisplayError("Cannot write to wininit.ini: ",TRUE,FALSE);
- }
-
- bstr_free(uninstlink,TRUE);
- bstr_free(uninstpath,TRUE);
- bstr_free(inipath,TRUE);
-}
-
DWORD WINAPI DoUninstall(LPVOID lpParam) {
InstData *idata;
HANDLE fin;
+ HWND delstat;
bstr *str;
char *startmenu,*desktop,*installdir;
t@@ -292,21 +60,22 @@ DWORD WINAPI DoUninstall(LPVOID lpParam) {
fin = CreateFile("install.log",GENERIC_READ,0,NULL,OPEN_EXISTING,0,NULL);
if (fin) {
- idata = ReadInstData(fin,product,installdir);
+ idata = ReadOldInstData(fin,product,installdir);
CloseHandle(fin);
+ DeleteFile("install.log");
RemoveService(idata->service);
- DeleteFile("install.log");
- DeleteFileList(idata->instfiles);
- DeleteFileList(idata->extrafiles);
+ delstat = GetDlgItem(mainDlg,ST_DELSTAT);
+ DeleteFileList(idata->instfiles,delstat,NULL);
+ DeleteFileList(idata->extrafiles,delstat,NULL);
startmenu = GetStartMenuDir(idata);
desktop = GetDesktopDir();
- DeleteLinkList(startmenu,idata->startmenu);
- DeleteLinkList(desktop,idata->desktop);
+ DeleteLinkList(startmenu,idata->startmenu,delstat);
+ DeleteLinkList(desktop,idata->desktop,delstat);
- RemoveUninstall(startmenu,product);
+ RemoveUninstall(startmenu,product,TRUE);
SetCurrentDirectory(desktop); /* Just make sure we're not in the install
directory any more */
(DIR) diff --git a/win32/util.c b/win32/util.c
t@@ -309,6 +309,7 @@ void FreeServiceDetails(NTService *service,BOOL freepts) {
void FreeInstData(InstData *idata,BOOL freepts) {
FreeFileList(idata->instfiles,freepts);
FreeFileList(idata->extrafiles,freepts);
+ FreeFileList(idata->keepfiles,freepts);
FreeLinkList(idata->startmenu,freepts);
FreeLinkList(idata->desktop,freepts);
t@@ -485,3 +486,249 @@ BOOL RemoveWholeDirectory(char *path) {
}
return TRUE;
}
+
+void RemoveService(NTService *service) {
+ SC_HANDLE scManager,scService;
+ SERVICE_STATUS status;
+
+ if (!service) return;
+
+ scManager = OpenSCManager(NULL,NULL,GENERIC_READ);
+
+ if (!scManager) {
+ DisplayError("Cannot connect to service manager",TRUE,FALSE);
+ return;
+ }
+
+ scService = OpenService(scManager,service->name,DELETE|SERVICE_STOP);
+ if (!scService) {
+ DisplayError("Cannot open service",TRUE,FALSE);
+ } else {
+ if (!ControlService(scService,SERVICE_CONTROL_STOP,&status) &&
+ GetLastError()!=ERROR_SERVICE_NOT_ACTIVE) {
+ DisplayError("Cannot stop service",TRUE,FALSE);
+ }
+ if (!DeleteService(scService)) {
+ DisplayError("Cannot delete service",TRUE,FALSE);
+ }
+ CloseServiceHandle(scService);
+ }
+
+ CloseServiceHandle(scManager);
+}
+
+char *read_line0(HANDLE hin) {
+ char *buf;
+ int bufsize=32,strind=0;
+ DWORD bytes_read;
+ buf = bmalloc(bufsize);
+
+ while (1) {
+ if (!ReadFile(hin,&buf[strind],1,&bytes_read,NULL)) {
+ printf("Read error\n"); break;
+ }
+ if (bytes_read==0) { buf[strind]='\0'; break; }
+ else if (buf[strind]=='\0') break;
+ else {
+ strind++;
+ if (strind>=bufsize) {
+ bufsize*=2;
+ buf = brealloc(buf,bufsize);
+ }
+ }
+ }
+ if (strind==0) { bfree(buf); return NULL; }
+ else return buf;
+}
+
+InstLink *ReadLinkList(HANDLE fin) {
+ InstLink *first=NULL,*listpt=NULL,*newpt;
+ char *linkfile,*origfile,*args;
+
+ while (1) {
+ linkfile=read_line0(fin);
+ if (!linkfile) break;
+ origfile=read_line0(fin);
+ args=read_line0(fin);
+ if (!origfile) DisplayError("Corrupt install.log",FALSE,TRUE);
+ newpt = bmalloc(sizeof(InstLink));
+ if (listpt) listpt->next = newpt;
+ else first = newpt;
+ listpt = newpt;
+ newpt->next=NULL;
+ newpt->linkfile=linkfile;
+ newpt->origfile=origfile;
+ newpt->args=args;
+ }
+ return first;
+}
+
+NTService *ReadServiceDetails(HANDLE fin) {
+ NTService *service=NULL;
+ char *name,*disp,*desc,*exe;
+
+ name = read_line0(fin);
+ if (name) {
+ disp = read_line0(fin);
+ desc = read_line0(fin);
+ exe = read_line0(fin);
+ if (!disp || !desc || !exe) {
+ DisplayError("Corrupt install.log",FALSE,TRUE);
+ } else {
+ AddServiceDetails(name,disp,desc,exe,&service);
+ }
+ }
+
+ return service;
+}
+
+InstFiles *ReadFileList(HANDLE fin) {
+ InstFiles *first=NULL,*listpt=NULL,*newpt;
+ char *filename,*filesize;
+
+ while (1) {
+ filename=read_line0(fin);
+ if (!filename) break;
+ filesize=read_line0(fin);
+ if (!filesize) DisplayError("Corrupt install.log",FALSE,TRUE);
+ newpt = bmalloc(sizeof(InstFiles));
+ if (listpt) listpt->next = newpt;
+ else first = newpt;
+ listpt = newpt;
+
+ newpt->next=NULL;
+ newpt->filename=filename;
+ newpt->filesize=atol(filesize);
+ bfree(filesize);
+ }
+ return first;
+}
+
+char *GetInstallDir(char *product) {
+ HKEY key;
+ bstr *str;
+ DWORD keytype,keylen;
+ char *installdir;
+
+ str=bstr_new();
+ bstr_assign(str,UninstallKey);
+ bstr_appendpath(str,product);
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,str->text,0,
+ KEY_ALL_ACCESS,&key)!=ERROR_SUCCESS) {
+ DisplayError("Could not open registry",FALSE,TRUE);
+ }
+
+ if (RegQueryValueEx(key,"InstallDirectory",NULL,
+ &keytype,NULL,&keylen)!=ERROR_SUCCESS ||
+ keytype!=REG_SZ) {
+ DisplayError("Could not query registry key",FALSE,TRUE);
+ }
+
+ installdir = bmalloc(keylen);
+ if (RegQueryValueEx(key,"InstallDirectory",NULL,
+ &keytype,installdir,&keylen)!=ERROR_SUCCESS) {
+ DisplayError("Could not get registry key value",FALSE,TRUE);
+ }
+
+ bstr_free(str,TRUE);
+ return installdir;
+}
+
+InstData *ReadOldInstData(HANDLE fin,char *product,char *installdir) {
+ InstData *idata;
+
+ idata=bmalloc(sizeof(InstData));
+
+ idata->product=product;
+ idata->installdir=installdir;
+ idata->startmenudir=read_line0(fin);
+
+ idata->instfiles = ReadFileList(fin);
+ idata->extrafiles = ReadFileList(fin);
+
+ idata->startmenu = ReadLinkList(fin);
+ idata->desktop = ReadLinkList(fin);
+
+ idata->service = ReadServiceDetails(fin);
+ idata->keepfiles = ReadFileList(fin);
+
+ return idata;
+}
+
+void DeleteFileList(InstFiles *listpt,HWND hwnd,InstFiles *keepfiles) {
+ bstr *str;
+ char *sep;
+ InstFiles *keeppt;
+
+ str=bstr_new();
+ for (;listpt;listpt=listpt->next) {
+ keeppt = keepfiles;
+ while (keeppt && strcmp(keeppt->filename,listpt->filename)!=0) {
+ keeppt = keeppt->next;
+ }
+ if (keeppt) {
+ keeppt->filesize=1; /* Mark that this file is already installed */
+ } else {
+ bstr_assign(str,"Deleting file: ");
+ bstr_append(str,listpt->filename);
+ SendMessage(hwnd,WM_SETTEXT,0,(LPARAM)str->text);
+ DeleteFile(listpt->filename);
+ sep = strrchr(listpt->filename,'\\');
+ if (sep) {
+ *sep = '\0';
+ RemoveWholeDirectory(listpt->filename);
+ *sep = '\\';
+ }
+ }
+ }
+ bstr_free(str,TRUE);
+}
+
+void DeleteLinkList(char *dir,InstLink *listpt,HWND hwnd) {
+ bstr *str;
+ str=bstr_new();
+ if (SetCurrentDirectory(dir)) {
+ for (;listpt;listpt=listpt->next) {
+ bstr_assign(str,"Deleting shortcut: ");
+ bstr_append(str,listpt->linkfile);
+ SendMessage(hwnd,WM_SETTEXT,0,(LPARAM)str->text);
+ DeleteFile(listpt->linkfile);
+ }
+ } else {
+ bstr_assign(str,"Could not find shortcut directory ");
+ bstr_append(str,dir);
+ DisplayError(str->text,TRUE,FALSE);
+ }
+ bstr_free(str,TRUE);
+}
+
+void RemoveUninstall(char *startmenu,char *product,BOOL delexe) {
+ bstr *inipath,*uninstpath,*uninstlink;
+
+ inipath=bstr_new();
+ uninstpath=bstr_new();
+ uninstlink=bstr_new();
+
+ bstr_assign(uninstlink,startmenu);
+ bstr_appendpath(uninstlink,"Uninstall ");
+ bstr_append(uninstlink,product);
+ bstr_append(uninstlink,".LNK");
+ DeleteFile(uninstlink->text);
+
+ if (delexe) {
+ bstr_assign_windir(inipath);
+ bstr_assign(uninstpath,inipath->text);
+
+ bstr_appendpath(inipath,"wininit.ini");
+ bstr_appendpath(uninstpath,UninstallEXE);
+
+ if (!WritePrivateProfileString("Renane","NUL",uninstpath->text,
+ inipath->text)) {
+ DisplayError("Cannot write to wininit.ini: ",TRUE,FALSE);
+ }
+ }
+
+ bstr_free(uninstlink,TRUE);
+ bstr_free(uninstpath,TRUE);
+ bstr_free(inipath,TRUE);
+}
(DIR) diff --git a/win32/util.h b/win32/util.h
t@@ -53,6 +53,7 @@ typedef struct _InstData {
NTService *service;
InstFiles *instfiles;
InstFiles *extrafiles;
+ InstFiles *keepfiles;
InstLink *startmenu;
InstLink *desktop;
} InstData;
t@@ -99,3 +100,9 @@ char *GetStartMenuDir(InstData *idata);
char *GetDesktopDir(void);
BOOL CreateWholeDirectory(char *path);
BOOL RemoveWholeDirectory(char *path);
+void DeleteLinkList(char *dir,InstLink *listpt,HWND hwnd);
+void DeleteFileList(InstFiles *listpt,HWND hwnd,InstFiles *keepfiles);
+InstData *ReadOldInstData(HANDLE fin,char *product,char *installdir);
+char *GetInstallDir(char *product);
+void RemoveService(NTService *service);
+void RemoveUninstall(char *startmenu,char *product,BOOL delexe);