/* * install.c (c) 1998,1999 Brian Smith * parts by Daniele Vistalli */ #include #include #include #include #include #include #if defined(__OS2__) || defined(__EMX__) || defined(WINNT) || defined(WIN32) #include #endif #include #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 0 && strncmp(&str1[z], str2, len2)==0) { int i; for(i=0;i (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, "") != NULL && (char *)strstr(tmpbuf, INSTALLER_VERSION) != NULL) found=linenum; } } if(found != -1) { rewind(tmplf); for (z=0;z") != 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, "") != 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,%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, ",%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, ",%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,%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, ",%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, ",%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,%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,%s\r\n\r\n", INSTALLER_APPLICATION, INSTALLER_VERSION); #endif /* Create nested subdirectories if necessary. */ strcpy(tmpinstallpath, installdir); for(k=3;k,%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, ",%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;j0) { char *tmpptr = &temp[0]; int len; strcpy(temp, INSTALLER_SYSLINE); temp[4999] = 0; len = strlen(temp); for(z=0;z,%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, ",%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;z0) { strcpy(temp, INSTALLER_SYSVAR); argn=0; arg1=&temp[0]; arg2=NULL; for(z=0;z