]> git.saurik.com Git - wxWidgets.git/blobdiff - utils/Install/install.c
merged 2.2 branch
[wxWidgets.git] / utils / Install / install.c
diff --git a/utils/Install/install.c b/utils/Install/install.c
new file mode 100644 (file)
index 0000000..1c29ce6
--- /dev/null
@@ -0,0 +1,1081 @@
+/*
+ *  install.c (c) 1998,1999 Brian Smith
+ *  parts by Daniele Vistalli
+ */
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <fcntl.h>
+#if defined(__OS2__) || defined(__EMX__) || defined(WINNT) || defined(WIN32)
+#include <process.h>
+#endif
+#include <sys/types.h>
+#include "install.h"
+#include "instsup.h"
+
+#if !defined(__EMX__) && !defined(__OS2__) && !defined(WIN32) && !defined(WINNT)
+#define stricmp strcasecmp
+#endif
+
+/* My Global variables ;) unusually many due to multiple dialogs */
+char tempPath[MAX_PATH];
+int installstate = NONE;
+int installstage = 0;
+int current_file=0, success=0;
+unsigned long int acepos=0, aceoffset=0;
+int pixels=0;
+char confirmstring[1024];
+/* I know I am being excessive but... better safe than sorry ;) */
+char *configsys[8196];
+int configfilecount=-1;
+int files = 0, files_deleted=0, packagesize=0, packagesselected[20];
+/* Global flags often set by the user */
+int driveselected, packagechosen, express = 1, driverstatus = -1, no_update = 0;
+int licensechecked = 0, custom = 0, checkforupdate = 1, downloadsite = 0;
+int usescitech = 1, usecurrent = 0, checking = 0, checkerror = 0, newerver = 0;
+char sddfilename[256] = "",  sddversion[256] = "",  sdddate[256] = "";
+char sddurl[4][256] = { "", "", "", "" };
+
+/* So these are accessible to REXX */
+int drivelist[26];
+FILE *self;
+
+/* These get loaded in loadheader */
+char *INSTALLER_APPLICATION;
+char *INSTALLER_VERSION;
+char *INSTALLER_TITLE;
+char *INSTALLER_PATH;
+char *INSTALLER_FOLDER;
+char *INSTALLER_PROGRAM;
+char *INSTALLER_SHADOW;
+char *INSTALLER_OBJECT;
+char *INSTALLER_SETS;
+char *INSTALLER_SYSVAR;
+char *INSTALLER_SYSLINE;
+char *INSTALLER_PACKAGES[20];
+char *INSTALLER_CONFIRM_WPS;
+char *INSTALLER_CONFIRM_CONFIGSYS;
+char *INSTALLER_CONFIRM_OVERWRITE;
+int INSTALLER_PACKAGE_COUNT;
+
+/* Will have to seperate this stuff to platform specifics... */
+
+/* Config.Sys -- Note the drive letter gets replaced with the boot drive letter
+                 It is just a place holder. (For the next 3 entries)             */
+char csfile[] = "C:\\CONFIG.SYS";
+/* Backup Config.Sys filename */
+char bufile[] = "C:\\CONFIG.SDD";
+/* Installation Log Database -- Used for uninstallation and aborting */
+#if defined(__OS2__) || defined(__EMX__) || defined(WINNT) || defined(WIN32)
+char instlog[] = "C:\\DBINST.LOG";
+#else
+char instlog[] = "~/dbinst.log";
+#endif
+char installdir[400];
+
+char bootdrive[2] = "C";
+char winpath[400] = "C:\\OS2\\MDOS\\WINOS2";
+char winjpath[400] = "C:\\OS2\\MDOS\\WINJOS2";
+char wintpath[400] = "C:\\OS2\\MDOS\\WINTOS2";
+char winhpath[400] = "C:\\OS2\\MDOS\\WINHOS2";
+char browsedir[400] = "C:\\";
+char installdir2[400] = "";
+char empty_string[] = "";
+char currentcf[400] = "";
+
+#ifdef ENABLE_LOGGING
+FILE *logfile;
+#endif
+
+/* Function prototypes */
+int installer_unpack(char *filename, int operation);
+void resetglobals(void);
+
+typedef struct _replacements {
+       char *replacestring, *replacevar;
+} Replacements;
+
+/* The variables in this array must be static buffers */
+Replacements InstRep[] = {
+       { "%INSTALLPATH%",   installdir },
+       { "%BOOTDRIVE%",     bootdrive },
+       { "%ANYSTRING%",     empty_string },
+       { "%WINPATH%",       winpath },
+       { "%WINJPATH%",      winjpath },
+       { "%WINTPATH%",      wintpath },
+       { "%WINHPATH%",      winhpath },
+       { "%USERPATH%",      installdir2 },
+       { "%VERSION%",       "1.0" }, /* This may be depricated */
+       { "%WEB_VER%",       sddversion },
+       { "%WEB_DATE%",      sdddate },
+       { "%WEB_LOCATION1%", sddurl[0] },
+       { "%WEB_LOCATION2%", sddurl[1] },
+       { "%WEB_LOCATION3%", sddurl[2] },
+       { "%WEB_LOCATION4%", sddurl[3] },
+       { "%PRI%",           "SVGA" }
+};
+int replacemax = 16;
+
+/* In str1, str2 gets replaced by str3 */
+char *replacestr(char *str1, char *str2, char *str3)
+{
+       char bigbuffer[4096];
+       int z, x=0, len1 = strlen(str1), len2 = strlen(str2), len3 = strlen(str3);
+
+       for(z=0;z<len1;z++)
+       {
+               if(len2 > 0 && strncmp(&str1[z], str2, len2)==0)
+               {
+                       int i;
+                       for(i=0;i<len3;i++)
+                       {
+                               bigbuffer[x] = str3[i];
+                               x++;
+                       }
+                       z=z+(len2-1);
+               } else {
+                       bigbuffer[x] = str1[z];
+                       x++;
+               }
+       }
+       bigbuffer[x] = 0;
+       return (char *)strdup(bigbuffer);
+}
+
+/* This function parses a string and replaces all the text in the
+ * Replacement array with the current dynamic text */
+char *replaceem(char *orig)
+{
+       char *tmp1 = NULL, *tmp2 = (char *)strdup(orig);
+       int z;
+
+       for(z=0;z<replacemax;z++)
+       {
+               tmp1 = replacestr(tmp2, InstRep[z].replacestring, InstRep[z].replacevar);
+               free(tmp2);
+               tmp2 = tmp1;
+               tmp1 = NULL;
+       }
+       return tmp2;
+}
+
+/*
+ * Find the offset withing the executable of the ace data for use.
+ */
+int aceseek_entry(int num)
+{
+       long headerstart;
+       char headerbuf[20], packageconfig[100];
+       int z, start = 0, entry = 0, packageoffset=0;
+       /* Decode DBSOFT-ACE - small memleak but
+        * install should not be running for very long. :) */
+       sprintf(headerbuf, "%s%d", decode("EEECFDEPEGFECNEBEDEF"), num);
+       if((headerstart = findtext(headerbuf)) < 0)
+       {
+               mesg("Could not find ACE header in executable.");
+               exit(2);
+       }
+
+       fseek(self, headerstart+strlen(headerbuf), SEEK_SET);
+       fread(packageconfig, 1, 100, self);
+
+       for(z=0;z<100;z++)
+       {
+               if(packageconfig[z] == '-' || packageconfig[z] == '*')
+               {
+                       char cur = packageconfig[z];
+                       packageconfig[z] = 0;
+                       switch(entry)
+                       {
+                       case 0:
+                               current_file = 0;
+                               files = atoi(&packageconfig[start]);
+                               break;
+                       case 1:
+                               packagesize = atoi(&packageconfig[start]);
+                               break;
+                       }
+                       start = z+1;
+                       if(cur == '*')
+                       {
+                               packageoffset = z + 1;
+                               z = 100;
+                       }
+                       entry++;
+               }
+       }
+       aceoffset=headerstart+strlen(headerbuf)+packageoffset;
+       fseek(self, aceoffset, SEEK_SET);
+       return TRUE;
+}
+
+/*
+ * Reads the embedded .cfg data from the executable and place it in the global
+ * INSTALL_* variables for use.
+ */
+int loadheader(void)
+{
+       char *buffer;
+       long headerstart;
+       int z, start=0, entry=0;
+
+       buffer = malloc(8096*4);
+
+       /* Decode DBSOFT-HEADER */
+       if((headerstart = findtext(decode("EEECFDEPEGFECNEIEFEBEEEFFC"))) < 0)
+       {
+               mesg("Could not find Selfinstaller header in executable.");
+               exit(2);
+       }
+       fseek(self, headerstart+13, SEEK_SET);
+
+       fread(buffer, 1, 8096*4, self);
+       for(z=0;z<8096*4;z++)
+       {
+               if(buffer[z] == '-' || buffer[z] == '*')
+               {
+                       char cur = buffer[z];
+                       buffer[z] = 0;
+                       switch(entry)
+                       {
+                       case 0:
+                               INSTALLER_APPLICATION = (char *)strdup(&buffer[start]);
+                               break;
+                       case 1:
+                               INSTALLER_VERSION = (char *)strdup(&buffer[start]);
+                               break;
+                       case 2:
+                               INSTALLER_TITLE = (char *)strdup(&buffer[start]);
+                               break;
+                       case 3:
+                               INSTALLER_PATH = (char *)strdup(&buffer[start]);
+                               break;
+                       case 4:
+                               INSTALLER_FOLDER = (char *)strdup(&buffer[start]);
+                               break;
+                       case 5:
+                               INSTALLER_PROGRAM = (char *)strdup(&buffer[start]);
+                               break;
+                       case 6:
+                               INSTALLER_SHADOW = (char *)strdup(&buffer[start]);
+                               break;
+                       case 7:
+                               INSTALLER_OBJECT = (char *)strdup(&buffer[start]);
+                               break;
+                       case 8:
+                               INSTALLER_SETS = (char *)strdup(&buffer[start]);
+                               break;
+                       case 9:
+                               INSTALLER_SYSVAR = (char *)strdup(&buffer[start]);
+                               break;
+                       case 10:
+                               INSTALLER_SYSLINE = (char *)strdup(&buffer[start]);
+                               break;
+                       case 11:
+                               INSTALLER_CONFIRM_WPS = (char *)strdup(&buffer[start]);
+                               break;
+                       case 12:
+                               INSTALLER_CONFIRM_CONFIGSYS = (char *)strdup(&buffer[start]);
+                               break;
+                       case 13:
+                               INSTALLER_CONFIRM_OVERWRITE = (char *)strdup(&buffer[start]);
+                               break;
+                       case 14:
+                               INSTALLER_PACKAGE_COUNT = atoi(&buffer[start]);
+                               break;
+                       default:
+                               INSTALLER_PACKAGES[entry-15] = malloc((z-start)+1);
+                               strcpy(INSTALLER_PACKAGES[entry-15], &buffer[start]);
+                               break;
+                       }
+                       start = z+1;
+                       if(cur == '*')
+                       {
+                               free(buffer);
+                               return TRUE;
+                       }
+
+                       entry++;
+               }
+       }
+       free(buffer);
+       return FALSE;
+}
+
+/*
+ * Functions to work on an ace file embedded within the archive in an
+ * abstract manner.
+ */
+int aceread(void *buf, size_t count)
+{
+       unsigned long curpos = ftell(self);
+       size_t readit;
+
+       if(count >  (packagesize-(curpos-aceoffset)))
+               readit = (packagesize-(curpos-aceoffset));
+       else
+               readit = count;
+
+       return fread(buf, 1, readit, self);
+}
+
+off_t acelseek(off_t offset, int whence)
+{
+       switch(whence)
+       {
+       case SEEK_SET:
+               fseek(self, aceoffset+offset, SEEK_SET);
+               break;
+       case SEEK_CUR:
+               fseek(self, offset, SEEK_CUR);
+               break;
+       }
+    acepos = ftell(self);
+       return acepos-aceoffset;
+}
+
+int aceopen(const char *path, int flags)
+{
+       fseek(self, aceoffset, SEEK_SET);
+       return 1;
+}
+
+int aceclose(int fd)
+{
+       fseek(self, aceoffset, SEEK_SET);
+       return  0;
+}
+
+int acesize(void)
+{
+       return packagesize;
+}
+
+int acetell(int fd)
+{
+       return ftell(self)-aceoffset;
+}
+
+/*
+ * Read the generated log file and remove any files installed.
+ */
+void delete_files(void)
+{
+       char tmpbuf[8196], *fileptr;
+       FILE *tmplf;
+       int linenum=0, found=-1, z;
+
+       files_deleted=1;
+
+       if((tmplf=fopen(instlog, "rb"))==NULL)
+               return;
+
+       while(!feof(tmplf))
+       {
+               fgets(tmpbuf, 8196, tmplf);
+               linenum++;
+               if(tmpbuf[0]=='[' && (char *)strstr(tmpbuf, INSTALLER_APPLICATION) != NULL && !feof(tmplf))
+               {
+                       fgets(tmpbuf, 8196, tmplf);
+                       linenum++;
+                       if((char *)strstr(tmpbuf, "<Version>") != NULL && (char *)strstr(tmpbuf, INSTALLER_VERSION) != NULL)
+                               found=linenum;
+               }
+       }
+       if(found != -1)
+       {
+               rewind(tmplf);
+               for (z=0;z<found;z++)
+                       fgets(tmpbuf, 8196, tmplf);
+               while(!feof(tmplf))
+               {
+                       fgets(tmpbuf, 8196, tmplf);
+                       if((char *)strstr(tmpbuf, "<FileInst>") != NULL)
+                       {
+                               fileptr = (char *)strchr(tmpbuf, ',')+1;
+                               /* Remove trailing CRLFs */
+                               if(fileptr[strlen(fileptr)-1] == '\r' || fileptr[strlen(fileptr)-1] == '\n')
+                                       fileptr[strlen(fileptr)-1]=0;
+                               if(fileptr[strlen(fileptr)-1] == '\r' || fileptr[strlen(fileptr)-1] == '\n')
+                                       fileptr[strlen(fileptr)-1]=0;
+                               remove(fileptr);
+                               current_file--;
+#if 0                          
+                               sendmessage(0, 1);
+#endif                         
+                       }
+                       if((char *)strstr(tmpbuf, "<End>") != NULL)
+                       {
+                               fclose(tmplf);
+                               return;
+                       }
+               }
+       }
+       fclose(tmplf);
+       return;
+}
+
+/*
+ * Reads a config file into memory for editing with updatesys, updateset, etc.
+ */
+int readconfigfile(char *filename)
+{
+       char tmpbuf[8196];
+       FILE *tmpcs;
+
+       /* Reset this value when restarting */
+       configfilecount = -1;
+
+       if((tmpcs=fopen(filename, "rb"))==NULL)
+       {
+               strcpy(currentcf, empty_string);
+               return 1;
+       }
+       else
+               strcpy(currentcf, filename);
+
+       while(!feof(tmpcs))
+       {
+               configfilecount++;
+               fgets(tmpbuf, 8196, tmpcs);
+               configsys[configfilecount] = malloc(strlen(tmpbuf)+1);
+               strcpy(configsys[configfilecount], tmpbuf);
+        stripcrlf(configsys[configfilecount]);
+       }
+
+       fclose(tmpcs);
+       return 0;
+}
+
+/*
+ * Write the updated config file to disk and backup the original.
+ */
+int writeconfigfile(char *filename, char *backup)
+{
+       FILE *tmpcs;
+       int i;
+
+       if(backup)
+       {
+               remove(backup);
+               rename(filename, backup);
+       }
+       else
+               remove(filename);
+
+       if((tmpcs=fopen(filename, "wb"))==NULL)
+               return 1;
+
+       for(i=0;i<configfilecount;i++)
+       {
+               if(configsys[i])
+               {
+                       fwrite(configsys[i], 1, strlen(configsys[i]), tmpcs);
+                       /* Add the CRLF that got stripped in the reading stage. */
+                       fwrite("\r\n", 1, 2, tmpcs);
+                       free(configsys[i]);
+               }
+       }
+
+       fclose(tmpcs);
+       return 0;
+}
+/*
+ * Adds or replaces a SET variable based on the flags (CONFIG.SYS)
+ */
+void updateset(char *setname, char *newvalue, int flag)
+{
+       char *cmpbuf1, *cmpbuf2, *tmpptr, *tmpptr2, *nv;
+       int i, z, t;
+
+       nv=replaceem(newvalue);
+
+       cmpbuf1=malloc(strlen(setname)+2);
+       strcpy(cmpbuf1, setname);
+       strcat(cmpbuf1, "=");
+       for(i=0;i<configfilecount;i++)
+       {
+               if(strlen(cmpbuf1) <= strlen(configsys[i]))
+               {
+                       tmpptr=(char *)strdup(configsys[i]);
+#if defined(__EMX__) || defined(__OS2__) || defined(WIN32) || defined(WINNT)
+                       strupr(tmpptr);
+#endif
+                       if((tmpptr2=(char*)strstr(tmpptr, "SET "))!=NULL)
+                       {
+                               tmpptr2 += 4;
+                               cmpbuf2=malloc(strlen(tmpptr2)+1);
+                               /* Remove any spaces from the string */
+                               z=0;
+                               for (t=0;t<strlen(tmpptr2) && z < strlen(cmpbuf1);t++)
+                               {
+                                       if(tmpptr2[t] != ' ')
+                                       {
+                                               cmpbuf2[z]=tmpptr2[t];
+                                               z++;
+                                       }
+                               }
+                               cmpbuf2[z]=0;
+                               if(stricmp(cmpbuf1, cmpbuf2) == 0)
+                               {
+                                       /* Ok we found the entry, and if UPDATE_ALWAYS change it to the
+                                        new entry, otherwise exit */
+                                       if(flag == UPDATE_ALWAYS)
+                                       {
+#ifdef ENABLE_LOGGING
+                                               fprintf(logfile, "<CFRemLine>,%s,%s\r\n", currentcf, configsys[i]);
+#endif
+                                               free(configsys[i]);
+                                               configsys[i] = malloc(strlen(setname)+strlen(nv)+6);
+                                               strcpy(configsys[i], "SET ");
+                                               strcat(configsys[i], setname);
+                                               strcat(configsys[i], "=");
+                                               strcat(configsys[i], nv);
+#ifdef ENABLE_LOGGING
+                                               fprintf(logfile, "<CFAddLine>,%s,%s\r\n", currentcf, configsys[i]);
+#endif
+                                               free(cmpbuf1);free(cmpbuf2);free(tmpptr);
+                                       }
+                                       return;
+                               }
+                               free(cmpbuf2);
+                       }
+                       free(tmpptr);
+               }
+       }
+       /* Couldn't find the line so we'll add it */
+       configsys[configfilecount]=malloc(strlen(cmpbuf1)+strlen(nv)+6);
+       strcpy(configsys[configfilecount], "SET ");
+       strcat(configsys[configfilecount], setname);
+       strcat(configsys[configfilecount], "=");
+       strcat(configsys[configfilecount], nv);
+#ifdef ENABLE_LOGGING
+       fprintf(logfile, "<CFAddLine>,%s,%s\r\n", currentcf, configsys[configfilecount]);
+#endif
+       configfilecount++;
+       free(cmpbuf1);
+}     
+
+/*
+ * Adds an entry to a system variable (CONFIG.SYS)
+ */
+void updatesys(char *sysname, char *newvalue)
+{
+       char *cmpbuf1, *cmpbuf2, *tmpptr, *tmpptr2, *capbuf1, *capbuf2, *nv, *brian;
+       int i, z, t;
+
+       nv=replaceem(newvalue);
+
+       cmpbuf1=malloc(strlen(sysname)+2);
+       strcpy(cmpbuf1, sysname);
+       strcat(cmpbuf1, "=");
+       for(i=0;i<configfilecount;i++)
+       {
+               if(strlen(cmpbuf1) <= strlen(configsys[i]))
+               {
+                       cmpbuf2=malloc(strlen(configsys[i])+1);
+                       /* Remove any spaces from the string */
+                       z=0;
+                       for (t=0;t<strlen(configsys[i]) && z < strlen(cmpbuf1);t++)
+                       {
+                               if(configsys[i][t] != ' ')
+                               {
+                                       cmpbuf2[z]=configsys[i][t];
+                                       z++;
+                               }
+                       }
+                       cmpbuf2[z]=0;
+                       if(stricmp(cmpbuf1, cmpbuf2) == 0)
+                       {
+                               /* Do a case insensitive comparison but preserve the case */
+                               tmpptr = &configsys[i][t];
+                               capbuf1=malloc(strlen(tmpptr)+1);
+                               capbuf2=malloc(strlen(nv)+1);
+                               strcpy(capbuf1, tmpptr);
+                               strcpy(capbuf2, nv);
+#if defined(__EMX__) || defined(__OS2__) || defined(WINNT) || defined(WIN32)                           
+                               strupr(capbuf1);
+                               strupr(capbuf2);
+#endif                         
+                               /* Ok, we found the line, and it doesn't have an entry so we'll add it */
+                               if((tmpptr2=(char *)strstr(capbuf1, capbuf2)) == NULL)
+                               {
+#ifdef ENABLE_LOGGING
+                                       fprintf(logfile, "<CFRemLine>,%s,%s\r\n", currentcf, configsys[i]);
+#endif
+                                       brian = configsys[i];
+                                       configsys[i] = malloc(strlen(configsys[i])+strlen(nv)+4);
+                                       strcpy(configsys[i], brian);
+                                       free(brian);
+                                       /* Remove any trailing CRLFs */
+                                       if(configsys[i][strlen(configsys[i])-1]!=';')
+                                               strcat(configsys[i], ";");
+                                       strcat(configsys[i], nv);
+                                       strcat(configsys[i], ";");
+#ifdef ENABLE_LOGGING
+                                       fprintf(logfile, "<CFAddLine>,%s,%s\r\n", currentcf, configsys[i]);
+#endif
+                               }
+                               free(cmpbuf1);free(cmpbuf2);free(capbuf1);free(capbuf2);
+                               return;
+                       }
+                       free(cmpbuf2);
+               }
+       }
+       /* Couldn't find the line so we'll add it */
+       configsys[configfilecount]=malloc(strlen(cmpbuf1)+strlen(nv)+3);
+       strcpy(configsys[configfilecount], cmpbuf1);
+       strcat(configsys[configfilecount], nv);
+       strcat(configsys[configfilecount], ";");
+#ifdef ENABLE_LOGGING
+       fprintf(logfile, "<CFAddLine>,%s,%s", currentcf, configsys[configfilecount]);
+#endif
+       configfilecount++;
+       free(cmpbuf1);
+       if(nv)
+               free(nv);
+}
+
+/*
+ * Removes a line from a config file.
+ */
+void removeline(char *text)
+{
+       int z;
+       for(z=0;z<configfilecount;z++)
+       {
+               if(stricmp(configsys[z], text) == 0)
+               {
+                       int t;
+
+#ifdef ENABLE_LOGGING
+                       fprintf(logfile, "<CFRemLine>,%s,%s\r\n", currentcf, configsys[z]);
+#endif
+                       free(configsys[z]);
+                       for(t=z;t<(configfilecount-1);t++)
+                               configsys[t] = configsys[t+1];
+                       configfilecount--;
+               }
+       }
+}
+
+
+/*
+ * The Window peocedure for the confirmation dialog.
+ */
+#if 0 
+MRESULT        EXPENTRY ConfirmDlgProc(HWND hWnd, ULONG msg, MPARAM mp1,       MPARAM mp2)
+{
+       SWP winpos;
+
+       switch (msg)
+       {
+       case WM_INITDLG:
+               WinSetWindowText(hWnd, INSTALLER_TITLE);
+               WinEnableWindow(WinWindowFromID(mainhwnd, I_Cancel), FALSE);
+               WinSetDlgItemText(hWnd, I_Confirm, confirmstring);
+               WinQueryWindowPos(mainhwnd, &winpos);
+               WinSetWindowPos(hWnd, HWND_TOP, winpos.x+30, winpos.y+30, 0, 0, SWP_MOVE | SWP_ZORDER);
+               break;
+       case WM_COMMAND:
+               WinEnableWindow(WinWindowFromID(mainhwnd, I_Cancel), TRUE);
+               switch ( SHORT1FROMMP(mp1) )
+               {
+               case I_Ja:
+                       WinDismissDlg(hWnd, 0);
+                       break;
+               case I_Alle:
+                       WinDismissDlg(hWnd, 1);
+                       break;
+               case I_Nein:
+                       WinDismissDlg(hWnd, 2);
+                       break;
+               case I_Halt:
+                       success=2;
+                       installstate=ABORTED;
+                       WinDismissDlg(hWnd, 3);
+                       break;
+               }
+               break;
+       default :
+               return(WinDefDlgProc(hWnd, msg, mp1, mp2));
+       }
+       return(0L);
+}
+#endif
+/*
+ * Display a confirmation dialog with the options: YES NO ALL CANCEL
+ * Returns: 0 for YES, 1 for ALL, 2 for NO and 3 for CANCEL
+ */
+int confirm(char *format, ...) {
+       va_list args;
+
+       /* if no confirmation, return 1, meaning overwrite all */
+       if (stricmp(INSTALLER_CONFIRM_OVERWRITE, "no") == 0)
+               return 1;
+
+       va_start(args, format);
+       vsprintf(confirmstring, format, args);
+       va_end(args);
+
+       /* Do something here in wxwindows */
+       return 1;
+}
+
+/*
+ * A function to grab a file from an embedded archive and extract it to the TEMP directory.
+ */
+void grabfile(char *filename)
+{
+       no_update = 1;
+       settempdir();
+       remove(filename);
+       aceseek_entry(0);
+       resetglobals();
+       installer_unpack(filename, 2);
+       no_update = 0;
+}
+
+/*
+ * This thread runs along side the main thread allowing the user to cancel the process.
+ */
+void install_thread(void *param)
+{
+       char tmpinstallpath[1024];
+       int  k, j, installcount=0, installed=0;
+
+       if(INSTALLER_PACKAGE_COUNT == 2)
+               packagesselected[1] = TRUE;
+                       
+       installstate = INSTALLING;
+
+#ifdef ENABLE_LOGGING
+       if((logfile=fopen(instlog, "ab"))==NULL)
+       {
+               error("Log file \"%s\" open failed! Installation aborted!", instlog);
+               exit(1);
+       }
+
+       fprintf(logfile, "[%s]\r\n<Version>,%s\r\n<Start>\r\n", INSTALLER_APPLICATION, INSTALLER_VERSION);
+#endif
+
+       /* Create nested subdirectories if necessary. */
+       strcpy(tmpinstallpath, installdir);
+       for(k=3;k<strlen(installdir);k++)
+       {
+               if(tmpinstallpath[k] == '\\')
+               {
+                       tmpinstallpath[k] = 0;
+#if defined(__EMX__) || defined(__CYGWIN__) || defined(UNIX)
+                       if (!mkdir(tmpinstallpath, 0))
+#else
+                       if (!mkdir(tmpinstallpath))
+#endif
+#ifdef ENABLE_LOGGING
+                               fprintf(logfile, "<NewDir>,%s\r\n", tmpinstallpath);
+#else
+                               ;
+#endif
+                       tmpinstallpath[k] = '\\';
+               }
+       }
+
+#if defined(__EMX__) || defined(__CYGWIN__) || defined(UNIX)
+                       if (!mkdir(installdir, 0))
+#else
+                       if (!mkdir(installdir))
+#endif
+#ifdef ENABLE_LOGGING
+               fprintf(logfile, "<NewDir>,%s\r\n", installdir);
+#else
+               ;
+#endif
+
+       /*if(strlen(installdir) > 0 && installdir[0] > 'a'-1 && installdir[0] < 'z'+1)
+               installdir[0]=installdir[0] - ('a'-'A');
+       if(strlen(installdir)>2 && installdir[1]==':' && installdir[2]=='\\')
+               DosSetDefaultDisk((int)(installdir[0]-'A'+1));*/
+
+       setdrivedir(installdir);
+
+       /* Unpack files to destination directory */
+       for(j=1;j<INSTALLER_PACKAGE_COUNT;j++)
+       {
+               if(packagesselected[j] == TRUE)
+                       installcount++;
+       }
+       if(installcount == 0)
+       {
+               mesg("No packages selected for installation!");
+       }
+       else
+       {
+               for(j=1;j<INSTALLER_PACKAGE_COUNT;j++)
+               {
+                       if(packagesselected[j] == TRUE)
+                       {
+#if 0                          
+                               char statustext[512];
+#endif                         
+                               aceseek_entry(j);
+                               resetglobals();
+#if 0
+                               sprintf(statustext,"Copying Files for %s %d/%d, Press \"Exit Installation\" to Abort.", INSTALLER_PACKAGES[j], installed+1, installcount);
+                               WinSetDlgItemText(mainhwnd,     I_Info3, statustext);
+#endif
+                               /* filename parameter when null is all files */
+                               installer_unpack(NULL, 2);
+                               installed++;
+                       }
+               }
+       }
+
+       if(success==1)
+       {
+               error("Error unpacking files, Installer may be corrupt!");
+       }
+
+       if(success==2)
+       {
+               error("User aborted installation!");
+       }
+
+       if(installstate != ABORTED)
+               installstate = COMPLETED;
+
+#if 0
+       sendmessage(0, 2);
+#endif 
+}
+
+/*
+ * Use the information from the .cfg file which is embedded in the EXE to update the
+ * CONFIG.SYS settings.
+ */
+void configsys_update(void)
+{
+       char *arg1, *arg2, *arg3;
+       char temp[5000];
+       int z, argn=0;
+
+       if(readconfigfile(csfile))
+               return;
+
+       /* Update Miscellaneous lines */
+       if(strlen(INSTALLER_SYSLINE)>0)
+       {
+               char *tmpptr = &temp[0];
+        int len;
+
+               strcpy(temp, INSTALLER_SYSLINE);
+               temp[4999] = 0;
+               len = strlen(temp);
+
+               for(z=0;z<len;z++)
+               {
+                       if(temp[z]==',')
+                       {
+                               char *tmpptr2;
+
+                               temp[z] = 0;
+                               tmpptr2 = replaceem(tmpptr);
+                               tmpptr = &temp[z+1];
+                               removeline(tmpptr2);
+                               configsys[configfilecount] = tmpptr2;
+#ifdef ENABLE_LOGGING
+                               fprintf(logfile, "<CFAddLine>,%s,%s\r\n", currentcf, tmpptr2);
+#endif
+                               configfilecount++;
+                       }
+               }
+               if(tmpptr && *tmpptr)
+               {
+                       char *tmpptr2;
+
+                       tmpptr2 = replaceem(tmpptr);
+                       removeline(tmpptr2);
+                       configsys[configfilecount] = tmpptr2;
+#ifdef ENABLE_LOGGING
+                       fprintf(logfile, "<CFAddLine>,%s,%s\r\n", currentcf, tmpptr2);
+#endif
+                       configfilecount++;
+               }
+
+       }
+       /* Update SET variables */
+       if(strlen(INSTALLER_SETS)>0)
+       {
+               strcpy(temp, INSTALLER_SETS);
+               argn=0;
+               arg1=&temp[0];
+               arg2=arg3=NULL;
+               for(z=0;z<strlen(INSTALLER_SETS);z++)
+               {
+                       if(temp[z]==',')
+                       {
+                               argn++;
+                               temp[z]=0;
+                               switch(argn)
+                               {
+                               case 1:
+                                       arg2=&temp[z+1];
+                                       break;
+                               case 2:
+                                       arg3=&temp[z+1];
+                                       break;
+                               case 3:
+                                       argn=0;
+                                       updateset(arg1, arg2, (int)(arg3[0]-'0'));
+                                       arg1=&temp[z+1];
+                                       arg2=arg3=NULL;
+                                       break;
+                               }
+                       }
+               }
+               if(arg3)
+                       updateset(arg1, arg2, (int)arg3-'0');
+       }
+       /* Update system variables */
+       if(strlen(INSTALLER_SYSVAR)>0)
+       {
+               strcpy(temp, INSTALLER_SYSVAR);
+               argn=0;
+               arg1=&temp[0];
+               arg2=NULL;
+               for(z=0;z<strlen(INSTALLER_SYSVAR);z++)
+               {
+                       if(temp[z]==',')
+                       {
+                               argn++;
+                               temp[z]=0;
+                               switch(argn)
+                               {
+                               case 1:
+                                       arg2=&temp[z+1];
+                                       break;
+                               case 2:
+                                       argn=0;
+                                       updatesys(arg1, arg2);
+                                       arg1=&temp[z+1];
+                                       arg2=NULL;
+                                       break;
+                               }
+                       }
+               }
+               if(arg2)
+                       updatesys(arg1, arg2);
+       }
+
+       writeconfigfile(csfile, bufile);
+}
+
+/*
+ * Reads a line from a file and returns it in raw.
+ */
+void getline(FILE *f, char *raw)
+{
+       memset(raw, 0, 256);
+       fgets(raw, 255, f);
+       stripcrlf(raw);
+}
+
+/*
+ * Removes a character from a buffer by advancing the buffer to the left.
+ */
+void removechar(char *buffer, int thisone, int len)
+{
+       int x;
+
+       for(x=thisone;x<len;x++)
+               buffer[x] = buffer[x+1];
+}
+
+/*
+ * Breaks up a line in raw into it's components.
+ */
+void parseline(char *raw, char comment, char delimiter, char quotes, char *entry, char *entrydata, char *entrydata2)
+{
+    char in[256];
+       int z, len, in_quotes = 0, entrynum=0, last = 0;
+
+       strcpy(entry, empty_string);
+       strcpy(entrydata, empty_string);
+       strcpy(entrydata2, empty_string);
+       strcpy(in, raw);
+
+       if(in[strlen(in)-1] == '\n')
+               in[strlen(in)-1] = 0;
+
+       if(in[0] != comment)
+       {
+        len=strlen(in);
+               for(z=0;z<len;z++)
+               {
+                       if(!in_quotes && in[z] == delimiter)
+                       {
+                               in[z] = 0;
+                               /* Strip any other delimiters */
+                               z++;
+                               while(in[z] == delimiter && z < len)
+                                       z++;
+                               if(!entrynum)
+                                       strcpy(entry, in);
+                               else
+                               {
+                                       strcpy(entrydata, &in[last]);
+                                       strcpy(entrydata2, &in[z]);
+                               }
+                               last = z;
+                               if(entrynum)
+                                       return;
+                               entrynum++;
+                       }
+                       if(in[z] == quotes)
+                       {
+                               removechar(in, z, len);
+                               z--;
+                               len--;
+                               if(in_quotes)
+                                       in_quotes = 0;
+                               else
+                                       in_quotes = 1;
+                       }
+               }
+               if(!entrynum)
+                       strcpy(entry, in);
+               else
+                       strcpy(entrydata, &in[last]);
+       }
+}
+
+/*
+ * Reads a line from the file and splits it up into it's components.
+ */
+int getparseline(FILE *f, char comment, char delimiter, char quotes, char *raw, char *entry, char *entrydata, char *entrydata2)
+{
+       getline(f, raw);
+       parseline(raw, comment, delimiter, quotes, entry, entrydata, entrydata2);
+       return strlen(raw);
+}
+
+
+void install_init(char *installername)
+{
+       if((self = fopen(installername, "rb")) == NULL)
+       {
+               mesg("Could not open SFX archive for reading!");
+               exit(1);
+       }
+       if(loadheader() == FALSE)
+       {
+               mesg("Could not load all required variables!");
+               exit(3);
+       }
+       strcpy(installdir, INSTALLER_PATH);
+}
+
+