]> git.saurik.com Git - wxWidgets.git/blame - utils/Install/install.c
nicer version compilation fix for wxUSE_WCHAR_T=0 (why should we duplicate definition...
[wxWidgets.git] / utils / Install / install.c
CommitLineData
f6bcfd97
BP
1/*
2 * install.c (c) 1998,1999 Brian Smith
3 * parts by Daniele Vistalli
4 */
5
6#include <stdio.h>
7#include <stddef.h>
8#include <stdlib.h>
9#include <stdarg.h>
10#include <string.h>
11#include <fcntl.h>
12#if defined(__OS2__) || defined(__EMX__) || defined(WINNT) || defined(WIN32)
13#include <process.h>
14#endif
15#include <sys/types.h>
16#include "install.h"
17#include "instsup.h"
18
19#if !defined(__EMX__) && !defined(__OS2__) && !defined(WIN32) && !defined(WINNT)
20#define stricmp strcasecmp
21#endif
22
23/* My Global variables ;) unusually many due to multiple dialogs */
24char tempPath[MAX_PATH];
25int installstate = NONE;
26int installstage = 0;
27int current_file=0, success=0;
28unsigned long int acepos=0, aceoffset=0;
29int pixels=0;
30char confirmstring[1024];
31/* I know I am being excessive but... better safe than sorry ;) */
32char *configsys[8196];
33int configfilecount=-1;
34int files = 0, files_deleted=0, packagesize=0, packagesselected[20];
35/* Global flags often set by the user */
36int driveselected, packagechosen, express = 1, driverstatus = -1, no_update = 0;
37int licensechecked = 0, custom = 0, checkforupdate = 1, downloadsite = 0;
38int usescitech = 1, usecurrent = 0, checking = 0, checkerror = 0, newerver = 0;
39char sddfilename[256] = "", sddversion[256] = "", sdddate[256] = "";
40char sddurl[4][256] = { "", "", "", "" };
41
42/* So these are accessible to REXX */
43int drivelist[26];
44FILE *self;
45
46/* These get loaded in loadheader */
47char *INSTALLER_APPLICATION;
48char *INSTALLER_VERSION;
49char *INSTALLER_TITLE;
50char *INSTALLER_PATH;
51char *INSTALLER_FOLDER;
52char *INSTALLER_PROGRAM;
53char *INSTALLER_SHADOW;
54char *INSTALLER_OBJECT;
55char *INSTALLER_SETS;
56char *INSTALLER_SYSVAR;
57char *INSTALLER_SYSLINE;
58char *INSTALLER_PACKAGES[20];
59char *INSTALLER_CONFIRM_WPS;
60char *INSTALLER_CONFIRM_CONFIGSYS;
61char *INSTALLER_CONFIRM_OVERWRITE;
62int INSTALLER_PACKAGE_COUNT;
63
64/* Will have to seperate this stuff to platform specifics... */
65
66/* Config.Sys -- Note the drive letter gets replaced with the boot drive letter
67 It is just a place holder. (For the next 3 entries) */
68char csfile[] = "C:\\CONFIG.SYS";
69/* Backup Config.Sys filename */
70char bufile[] = "C:\\CONFIG.SDD";
71/* Installation Log Database -- Used for uninstallation and aborting */
72#if defined(__OS2__) || defined(__EMX__) || defined(WINNT) || defined(WIN32)
73char instlog[] = "C:\\DBINST.LOG";
74#else
75char instlog[] = "~/dbinst.log";
76#endif
77char installdir[400];
78
79char bootdrive[2] = "C";
80char winpath[400] = "C:\\OS2\\MDOS\\WINOS2";
81char winjpath[400] = "C:\\OS2\\MDOS\\WINJOS2";
82char wintpath[400] = "C:\\OS2\\MDOS\\WINTOS2";
83char winhpath[400] = "C:\\OS2\\MDOS\\WINHOS2";
84char browsedir[400] = "C:\\";
85char installdir2[400] = "";
86char empty_string[] = "";
87char currentcf[400] = "";
88
89#ifdef ENABLE_LOGGING
90FILE *logfile;
91#endif
92
93/* Function prototypes */
94int installer_unpack(char *filename, int operation);
95void resetglobals(void);
96
97typedef struct _replacements {
98 char *replacestring, *replacevar;
99} Replacements;
100
101/* The variables in this array must be static buffers */
102Replacements InstRep[] = {
103 { "%INSTALLPATH%", installdir },
104 { "%BOOTDRIVE%", bootdrive },
105 { "%ANYSTRING%", empty_string },
106 { "%WINPATH%", winpath },
107 { "%WINJPATH%", winjpath },
108 { "%WINTPATH%", wintpath },
109 { "%WINHPATH%", winhpath },
110 { "%USERPATH%", installdir2 },
111 { "%VERSION%", "1.0" }, /* This may be depricated */
112 { "%WEB_VER%", sddversion },
113 { "%WEB_DATE%", sdddate },
114 { "%WEB_LOCATION1%", sddurl[0] },
115 { "%WEB_LOCATION2%", sddurl[1] },
116 { "%WEB_LOCATION3%", sddurl[2] },
117 { "%WEB_LOCATION4%", sddurl[3] },
118 { "%PRI%", "SVGA" }
119};
120int replacemax = 16;
121
122/* In str1, str2 gets replaced by str3 */
123char *replacestr(char *str1, char *str2, char *str3)
124{
125 char bigbuffer[4096];
126 int z, x=0, len1 = strlen(str1), len2 = strlen(str2), len3 = strlen(str3);
127
128 for(z=0;z<len1;z++)
129 {
130 if(len2 > 0 && strncmp(&str1[z], str2, len2)==0)
131 {
132 int i;
133 for(i=0;i<len3;i++)
134 {
135 bigbuffer[x] = str3[i];
136 x++;
137 }
138 z=z+(len2-1);
139 } else {
140 bigbuffer[x] = str1[z];
141 x++;
142 }
143 }
144 bigbuffer[x] = 0;
145 return (char *)strdup(bigbuffer);
146}
147
148/* This function parses a string and replaces all the text in the
149 * Replacement array with the current dynamic text */
150char *replaceem(char *orig)
151{
152 char *tmp1 = NULL, *tmp2 = (char *)strdup(orig);
153 int z;
154
155 for(z=0;z<replacemax;z++)
156 {
157 tmp1 = replacestr(tmp2, InstRep[z].replacestring, InstRep[z].replacevar);
158 free(tmp2);
159 tmp2 = tmp1;
160 tmp1 = NULL;
161 }
162 return tmp2;
163}
164
165/*
166 * Find the offset withing the executable of the ace data for use.
167 */
168int aceseek_entry(int num)
169{
170 long headerstart;
171 char headerbuf[20], packageconfig[100];
172 int z, start = 0, entry = 0, packageoffset=0;
173 /* Decode DBSOFT-ACE - small memleak but
174 * install should not be running for very long. :) */
175 sprintf(headerbuf, "%s%d", decode("EEECFDEPEGFECNEBEDEF"), num);
176 if((headerstart = findtext(headerbuf)) < 0)
177 {
178 mesg("Could not find ACE header in executable.");
179 exit(2);
180 }
181
182 fseek(self, headerstart+strlen(headerbuf), SEEK_SET);
183 fread(packageconfig, 1, 100, self);
184
185 for(z=0;z<100;z++)
186 {
187 if(packageconfig[z] == '-' || packageconfig[z] == '*')
188 {
189 char cur = packageconfig[z];
190 packageconfig[z] = 0;
191 switch(entry)
192 {
193 case 0:
194 current_file = 0;
195 files = atoi(&packageconfig[start]);
196 break;
197 case 1:
198 packagesize = atoi(&packageconfig[start]);
199 break;
200 }
201 start = z+1;
202 if(cur == '*')
203 {
204 packageoffset = z + 1;
205 z = 100;
206 }
207 entry++;
208 }
209 }
210 aceoffset=headerstart+strlen(headerbuf)+packageoffset;
211 fseek(self, aceoffset, SEEK_SET);
212 return TRUE;
213}
214
215/*
216 * Reads the embedded .cfg data from the executable and place it in the global
217 * INSTALL_* variables for use.
218 */
219int loadheader(void)
220{
221 char *buffer;
222 long headerstart;
223 int z, start=0, entry=0;
224
225 buffer = malloc(8096*4);
226
227 /* Decode DBSOFT-HEADER */
228 if((headerstart = findtext(decode("EEECFDEPEGFECNEIEFEBEEEFFC"))) < 0)
229 {
230 mesg("Could not find Selfinstaller header in executable.");
231 exit(2);
232 }
233 fseek(self, headerstart+13, SEEK_SET);
234
235 fread(buffer, 1, 8096*4, self);
236 for(z=0;z<8096*4;z++)
237 {
238 if(buffer[z] == '-' || buffer[z] == '*')
239 {
240 char cur = buffer[z];
241 buffer[z] = 0;
242 switch(entry)
243 {
244 case 0:
245 INSTALLER_APPLICATION = (char *)strdup(&buffer[start]);
246 break;
247 case 1:
248 INSTALLER_VERSION = (char *)strdup(&buffer[start]);
249 break;
250 case 2:
251 INSTALLER_TITLE = (char *)strdup(&buffer[start]);
252 break;
253 case 3:
254 INSTALLER_PATH = (char *)strdup(&buffer[start]);
255 break;
256 case 4:
257 INSTALLER_FOLDER = (char *)strdup(&buffer[start]);
258 break;
259 case 5:
260 INSTALLER_PROGRAM = (char *)strdup(&buffer[start]);
261 break;
262 case 6:
263 INSTALLER_SHADOW = (char *)strdup(&buffer[start]);
264 break;
265 case 7:
266 INSTALLER_OBJECT = (char *)strdup(&buffer[start]);
267 break;
268 case 8:
269 INSTALLER_SETS = (char *)strdup(&buffer[start]);
270 break;
271 case 9:
272 INSTALLER_SYSVAR = (char *)strdup(&buffer[start]);
273 break;
274 case 10:
275 INSTALLER_SYSLINE = (char *)strdup(&buffer[start]);
276 break;
277 case 11:
278 INSTALLER_CONFIRM_WPS = (char *)strdup(&buffer[start]);
279 break;
280 case 12:
281 INSTALLER_CONFIRM_CONFIGSYS = (char *)strdup(&buffer[start]);
282 break;
283 case 13:
284 INSTALLER_CONFIRM_OVERWRITE = (char *)strdup(&buffer[start]);
285 break;
286 case 14:
287 INSTALLER_PACKAGE_COUNT = atoi(&buffer[start]);
288 break;
289 default:
290 INSTALLER_PACKAGES[entry-15] = malloc((z-start)+1);
291 strcpy(INSTALLER_PACKAGES[entry-15], &buffer[start]);
292 break;
293 }
294 start = z+1;
295 if(cur == '*')
296 {
297 free(buffer);
298 return TRUE;
299 }
300
301 entry++;
302 }
303 }
304 free(buffer);
305 return FALSE;
306}
307
308/*
309 * Functions to work on an ace file embedded within the archive in an
310 * abstract manner.
311 */
312int aceread(void *buf, size_t count)
313{
314 unsigned long curpos = ftell(self);
315 size_t readit;
316
317 if(count > (packagesize-(curpos-aceoffset)))
318 readit = (packagesize-(curpos-aceoffset));
319 else
320 readit = count;
321
322 return fread(buf, 1, readit, self);
323}
324
325off_t acelseek(off_t offset, int whence)
326{
327 switch(whence)
328 {
329 case SEEK_SET:
330 fseek(self, aceoffset+offset, SEEK_SET);
331 break;
332 case SEEK_CUR:
333 fseek(self, offset, SEEK_CUR);
334 break;
335 }
336 acepos = ftell(self);
337 return acepos-aceoffset;
338}
339
340int aceopen(const char *path, int flags)
341{
342 fseek(self, aceoffset, SEEK_SET);
343 return 1;
344}
345
346int aceclose(int fd)
347{
348 fseek(self, aceoffset, SEEK_SET);
349 return 0;
350}
351
352int acesize(void)
353{
354 return packagesize;
355}
356
357int acetell(int fd)
358{
359 return ftell(self)-aceoffset;
360}
361
362/*
363 * Read the generated log file and remove any files installed.
364 */
365void delete_files(void)
366{
367 char tmpbuf[8196], *fileptr;
368 FILE *tmplf;
369 int linenum=0, found=-1, z;
370
371 files_deleted=1;
372
373 if((tmplf=fopen(instlog, "rb"))==NULL)
374 return;
375
376 while(!feof(tmplf))
377 {
378 fgets(tmpbuf, 8196, tmplf);
379 linenum++;
380 if(tmpbuf[0]=='[' && (char *)strstr(tmpbuf, INSTALLER_APPLICATION) != NULL && !feof(tmplf))
381 {
382 fgets(tmpbuf, 8196, tmplf);
383 linenum++;
384 if((char *)strstr(tmpbuf, "<Version>") != NULL && (char *)strstr(tmpbuf, INSTALLER_VERSION) != NULL)
385 found=linenum;
386 }
387 }
388 if(found != -1)
389 {
390 rewind(tmplf);
391 for (z=0;z<found;z++)
392 fgets(tmpbuf, 8196, tmplf);
393 while(!feof(tmplf))
394 {
395 fgets(tmpbuf, 8196, tmplf);
396 if((char *)strstr(tmpbuf, "<FileInst>") != NULL)
397 {
398 fileptr = (char *)strchr(tmpbuf, ',')+1;
399 /* Remove trailing CRLFs */
400 if(fileptr[strlen(fileptr)-1] == '\r' || fileptr[strlen(fileptr)-1] == '\n')
401 fileptr[strlen(fileptr)-1]=0;
402 if(fileptr[strlen(fileptr)-1] == '\r' || fileptr[strlen(fileptr)-1] == '\n')
403 fileptr[strlen(fileptr)-1]=0;
404 remove(fileptr);
405 current_file--;
406#if 0
407 sendmessage(0, 1);
408#endif
409 }
410 if((char *)strstr(tmpbuf, "<End>") != NULL)
411 {
412 fclose(tmplf);
413 return;
414 }
415 }
416 }
417 fclose(tmplf);
418 return;
419}
420
421/*
422 * Reads a config file into memory for editing with updatesys, updateset, etc.
423 */
424int readconfigfile(char *filename)
425{
426 char tmpbuf[8196];
427 FILE *tmpcs;
428
429 /* Reset this value when restarting */
430 configfilecount = -1;
431
432 if((tmpcs=fopen(filename, "rb"))==NULL)
433 {
434 strcpy(currentcf, empty_string);
435 return 1;
436 }
437 else
438 strcpy(currentcf, filename);
439
440 while(!feof(tmpcs))
441 {
442 configfilecount++;
443 fgets(tmpbuf, 8196, tmpcs);
444 configsys[configfilecount] = malloc(strlen(tmpbuf)+1);
445 strcpy(configsys[configfilecount], tmpbuf);
446 stripcrlf(configsys[configfilecount]);
447 }
448
449 fclose(tmpcs);
450 return 0;
451}
452
453/*
454 * Write the updated config file to disk and backup the original.
455 */
456int writeconfigfile(char *filename, char *backup)
457{
458 FILE *tmpcs;
459 int i;
460
461 if(backup)
462 {
463 remove(backup);
464 rename(filename, backup);
465 }
466 else
467 remove(filename);
468
469 if((tmpcs=fopen(filename, "wb"))==NULL)
470 return 1;
471
472 for(i=0;i<configfilecount;i++)
473 {
474 if(configsys[i])
475 {
476 fwrite(configsys[i], 1, strlen(configsys[i]), tmpcs);
477 /* Add the CRLF that got stripped in the reading stage. */
478 fwrite("\r\n", 1, 2, tmpcs);
479 free(configsys[i]);
480 }
481 }
482
483 fclose(tmpcs);
484 return 0;
485}
486/*
487 * Adds or replaces a SET variable based on the flags (CONFIG.SYS)
488 */
489void updateset(char *setname, char *newvalue, int flag)
490{
491 char *cmpbuf1, *cmpbuf2, *tmpptr, *tmpptr2, *nv;
492 int i, z, t;
493
494 nv=replaceem(newvalue);
495
496 cmpbuf1=malloc(strlen(setname)+2);
497 strcpy(cmpbuf1, setname);
498 strcat(cmpbuf1, "=");
499 for(i=0;i<configfilecount;i++)
500 {
501 if(strlen(cmpbuf1) <= strlen(configsys[i]))
502 {
503 tmpptr=(char *)strdup(configsys[i]);
504#if defined(__EMX__) || defined(__OS2__) || defined(WIN32) || defined(WINNT)
505 strupr(tmpptr);
506#endif
507 if((tmpptr2=(char*)strstr(tmpptr, "SET "))!=NULL)
508 {
509 tmpptr2 += 4;
510 cmpbuf2=malloc(strlen(tmpptr2)+1);
511 /* Remove any spaces from the string */
512 z=0;
513 for (t=0;t<strlen(tmpptr2) && z < strlen(cmpbuf1);t++)
514 {
515 if(tmpptr2[t] != ' ')
516 {
517 cmpbuf2[z]=tmpptr2[t];
518 z++;
519 }
520 }
521 cmpbuf2[z]=0;
522 if(stricmp(cmpbuf1, cmpbuf2) == 0)
523 {
524 /* Ok we found the entry, and if UPDATE_ALWAYS change it to the
525 new entry, otherwise exit */
526 if(flag == UPDATE_ALWAYS)
527 {
528#ifdef ENABLE_LOGGING
529 fprintf(logfile, "<CFRemLine>,%s,%s\r\n", currentcf, configsys[i]);
530#endif
531 free(configsys[i]);
532 configsys[i] = malloc(strlen(setname)+strlen(nv)+6);
533 strcpy(configsys[i], "SET ");
534 strcat(configsys[i], setname);
535 strcat(configsys[i], "=");
536 strcat(configsys[i], nv);
537#ifdef ENABLE_LOGGING
538 fprintf(logfile, "<CFAddLine>,%s,%s\r\n", currentcf, configsys[i]);
539#endif
540 free(cmpbuf1);free(cmpbuf2);free(tmpptr);
541 }
542 return;
543 }
544 free(cmpbuf2);
545 }
546 free(tmpptr);
547 }
548 }
549 /* Couldn't find the line so we'll add it */
550 configsys[configfilecount]=malloc(strlen(cmpbuf1)+strlen(nv)+6);
551 strcpy(configsys[configfilecount], "SET ");
552 strcat(configsys[configfilecount], setname);
553 strcat(configsys[configfilecount], "=");
554 strcat(configsys[configfilecount], nv);
555#ifdef ENABLE_LOGGING
556 fprintf(logfile, "<CFAddLine>,%s,%s\r\n", currentcf, configsys[configfilecount]);
557#endif
558 configfilecount++;
559 free(cmpbuf1);
560}
561
562/*
563 * Adds an entry to a system variable (CONFIG.SYS)
564 */
565void updatesys(char *sysname, char *newvalue)
566{
567 char *cmpbuf1, *cmpbuf2, *tmpptr, *tmpptr2, *capbuf1, *capbuf2, *nv, *brian;
568 int i, z, t;
569
570 nv=replaceem(newvalue);
571
572 cmpbuf1=malloc(strlen(sysname)+2);
573 strcpy(cmpbuf1, sysname);
574 strcat(cmpbuf1, "=");
575 for(i=0;i<configfilecount;i++)
576 {
577 if(strlen(cmpbuf1) <= strlen(configsys[i]))
578 {
579 cmpbuf2=malloc(strlen(configsys[i])+1);
580 /* Remove any spaces from the string */
581 z=0;
582 for (t=0;t<strlen(configsys[i]) && z < strlen(cmpbuf1);t++)
583 {
584 if(configsys[i][t] != ' ')
585 {
586 cmpbuf2[z]=configsys[i][t];
587 z++;
588 }
589 }
590 cmpbuf2[z]=0;
591 if(stricmp(cmpbuf1, cmpbuf2) == 0)
592 {
593 /* Do a case insensitive comparison but preserve the case */
594 tmpptr = &configsys[i][t];
595 capbuf1=malloc(strlen(tmpptr)+1);
596 capbuf2=malloc(strlen(nv)+1);
597 strcpy(capbuf1, tmpptr);
598 strcpy(capbuf2, nv);
599#if defined(__EMX__) || defined(__OS2__) || defined(WINNT) || defined(WIN32)
600 strupr(capbuf1);
601 strupr(capbuf2);
602#endif
603 /* Ok, we found the line, and it doesn't have an entry so we'll add it */
604 if((tmpptr2=(char *)strstr(capbuf1, capbuf2)) == NULL)
605 {
606#ifdef ENABLE_LOGGING
607 fprintf(logfile, "<CFRemLine>,%s,%s\r\n", currentcf, configsys[i]);
608#endif
609 brian = configsys[i];
610 configsys[i] = malloc(strlen(configsys[i])+strlen(nv)+4);
611 strcpy(configsys[i], brian);
612 free(brian);
613 /* Remove any trailing CRLFs */
614 if(configsys[i][strlen(configsys[i])-1]!=';')
615 strcat(configsys[i], ";");
616 strcat(configsys[i], nv);
617 strcat(configsys[i], ";");
618#ifdef ENABLE_LOGGING
619 fprintf(logfile, "<CFAddLine>,%s,%s\r\n", currentcf, configsys[i]);
620#endif
621 }
622 free(cmpbuf1);free(cmpbuf2);free(capbuf1);free(capbuf2);
623 return;
624 }
625 free(cmpbuf2);
626 }
627 }
628 /* Couldn't find the line so we'll add it */
629 configsys[configfilecount]=malloc(strlen(cmpbuf1)+strlen(nv)+3);
630 strcpy(configsys[configfilecount], cmpbuf1);
631 strcat(configsys[configfilecount], nv);
632 strcat(configsys[configfilecount], ";");
633#ifdef ENABLE_LOGGING
634 fprintf(logfile, "<CFAddLine>,%s,%s", currentcf, configsys[configfilecount]);
635#endif
636 configfilecount++;
637 free(cmpbuf1);
638 if(nv)
639 free(nv);
640}
641
642/*
643 * Removes a line from a config file.
644 */
645void removeline(char *text)
646{
647 int z;
648 for(z=0;z<configfilecount;z++)
649 {
650 if(stricmp(configsys[z], text) == 0)
651 {
652 int t;
653
654#ifdef ENABLE_LOGGING
655 fprintf(logfile, "<CFRemLine>,%s,%s\r\n", currentcf, configsys[z]);
656#endif
657 free(configsys[z]);
658 for(t=z;t<(configfilecount-1);t++)
659 configsys[t] = configsys[t+1];
660 configfilecount--;
661 }
662 }
663}
664
665
666/*
667 * The Window peocedure for the confirmation dialog.
668 */
669#if 0
670MRESULT EXPENTRY ConfirmDlgProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
671{
672 SWP winpos;
673
674 switch (msg)
675 {
676 case WM_INITDLG:
677 WinSetWindowText(hWnd, INSTALLER_TITLE);
678 WinEnableWindow(WinWindowFromID(mainhwnd, I_Cancel), FALSE);
679 WinSetDlgItemText(hWnd, I_Confirm, confirmstring);
680 WinQueryWindowPos(mainhwnd, &winpos);
681 WinSetWindowPos(hWnd, HWND_TOP, winpos.x+30, winpos.y+30, 0, 0, SWP_MOVE | SWP_ZORDER);
682 break;
683 case WM_COMMAND:
684 WinEnableWindow(WinWindowFromID(mainhwnd, I_Cancel), TRUE);
685 switch ( SHORT1FROMMP(mp1) )
686 {
687 case I_Ja:
688 WinDismissDlg(hWnd, 0);
689 break;
690 case I_Alle:
691 WinDismissDlg(hWnd, 1);
692 break;
693 case I_Nein:
694 WinDismissDlg(hWnd, 2);
695 break;
696 case I_Halt:
697 success=2;
698 installstate=ABORTED;
699 WinDismissDlg(hWnd, 3);
700 break;
701 }
702 break;
703 default :
704 return(WinDefDlgProc(hWnd, msg, mp1, mp2));
705 }
706 return(0L);
707}
708#endif
709/*
710 * Display a confirmation dialog with the options: YES NO ALL CANCEL
711 * Returns: 0 for YES, 1 for ALL, 2 for NO and 3 for CANCEL
712 */
713int confirm(char *format, ...) {
714 va_list args;
715
716 /* if no confirmation, return 1, meaning overwrite all */
717 if (stricmp(INSTALLER_CONFIRM_OVERWRITE, "no") == 0)
718 return 1;
719
720 va_start(args, format);
721 vsprintf(confirmstring, format, args);
722 va_end(args);
723
724 /* Do something here in wxwindows */
725 return 1;
726}
727
728/*
729 * A function to grab a file from an embedded archive and extract it to the TEMP directory.
730 */
731void grabfile(char *filename)
732{
733 no_update = 1;
734 settempdir();
735 remove(filename);
736 aceseek_entry(0);
737 resetglobals();
738 installer_unpack(filename, 2);
739 no_update = 0;
740}
741
742/*
743 * This thread runs along side the main thread allowing the user to cancel the process.
744 */
745void install_thread(void *param)
746{
747 char tmpinstallpath[1024];
748 int k, j, installcount=0, installed=0;
749
750 if(INSTALLER_PACKAGE_COUNT == 2)
751 packagesselected[1] = TRUE;
752
753 installstate = INSTALLING;
754
755#ifdef ENABLE_LOGGING
756 if((logfile=fopen(instlog, "ab"))==NULL)
757 {
758 error("Log file \"%s\" open failed! Installation aborted!", instlog);
759 exit(1);
760 }
761
762 fprintf(logfile, "[%s]\r\n<Version>,%s\r\n<Start>\r\n", INSTALLER_APPLICATION, INSTALLER_VERSION);
763#endif
764
765 /* Create nested subdirectories if necessary. */
766 strcpy(tmpinstallpath, installdir);
767 for(k=3;k<strlen(installdir);k++)
768 {
769 if(tmpinstallpath[k] == '\\')
770 {
771 tmpinstallpath[k] = 0;
772#if defined(__EMX__) || defined(__CYGWIN__) || defined(UNIX)
773 if (!mkdir(tmpinstallpath, 0))
774#else
775 if (!mkdir(tmpinstallpath))
776#endif
777#ifdef ENABLE_LOGGING
778 fprintf(logfile, "<NewDir>,%s\r\n", tmpinstallpath);
779#else
780 ;
781#endif
782 tmpinstallpath[k] = '\\';
783 }
784 }
785
786#if defined(__EMX__) || defined(__CYGWIN__) || defined(UNIX)
787 if (!mkdir(installdir, 0))
788#else
789 if (!mkdir(installdir))
790#endif
791#ifdef ENABLE_LOGGING
792 fprintf(logfile, "<NewDir>,%s\r\n", installdir);
793#else
794 ;
795#endif
796
797 /*if(strlen(installdir) > 0 && installdir[0] > 'a'-1 && installdir[0] < 'z'+1)
798 installdir[0]=installdir[0] - ('a'-'A');
799 if(strlen(installdir)>2 && installdir[1]==':' && installdir[2]=='\\')
800 DosSetDefaultDisk((int)(installdir[0]-'A'+1));*/
801
802 setdrivedir(installdir);
803
804 /* Unpack files to destination directory */
805 for(j=1;j<INSTALLER_PACKAGE_COUNT;j++)
806 {
807 if(packagesselected[j] == TRUE)
808 installcount++;
809 }
810 if(installcount == 0)
811 {
812 mesg("No packages selected for installation!");
813 }
814 else
815 {
816 for(j=1;j<INSTALLER_PACKAGE_COUNT;j++)
817 {
818 if(packagesselected[j] == TRUE)
819 {
820#if 0
821 char statustext[512];
822#endif
823 aceseek_entry(j);
824 resetglobals();
825#if 0
826 sprintf(statustext,"Copying Files for %s %d/%d, Press \"Exit Installation\" to Abort.", INSTALLER_PACKAGES[j], installed+1, installcount);
827 WinSetDlgItemText(mainhwnd, I_Info3, statustext);
828#endif
829 /* filename parameter when null is all files */
830 installer_unpack(NULL, 2);
831 installed++;
832 }
833 }
834 }
835
836 if(success==1)
837 {
838 error("Error unpacking files, Installer may be corrupt!");
839 }
840
841 if(success==2)
842 {
843 error("User aborted installation!");
844 }
845
846 if(installstate != ABORTED)
847 installstate = COMPLETED;
848
849#if 0
850 sendmessage(0, 2);
851#endif
852}
853
854/*
855 * Use the information from the .cfg file which is embedded in the EXE to update the
856 * CONFIG.SYS settings.
857 */
858void configsys_update(void)
859{
860 char *arg1, *arg2, *arg3;
861 char temp[5000];
862 int z, argn=0;
863
864 if(readconfigfile(csfile))
865 return;
866
867 /* Update Miscellaneous lines */
868 if(strlen(INSTALLER_SYSLINE)>0)
869 {
870 char *tmpptr = &temp[0];
871 int len;
872
873 strcpy(temp, INSTALLER_SYSLINE);
874 temp[4999] = 0;
875 len = strlen(temp);
876
877 for(z=0;z<len;z++)
878 {
879 if(temp[z]==',')
880 {
881 char *tmpptr2;
882
883 temp[z] = 0;
884 tmpptr2 = replaceem(tmpptr);
885 tmpptr = &temp[z+1];
886 removeline(tmpptr2);
887 configsys[configfilecount] = tmpptr2;
888#ifdef ENABLE_LOGGING
889 fprintf(logfile, "<CFAddLine>,%s,%s\r\n", currentcf, tmpptr2);
890#endif
891 configfilecount++;
892 }
893 }
894 if(tmpptr && *tmpptr)
895 {
896 char *tmpptr2;
897
898 tmpptr2 = replaceem(tmpptr);
899 removeline(tmpptr2);
900 configsys[configfilecount] = tmpptr2;
901#ifdef ENABLE_LOGGING
902 fprintf(logfile, "<CFAddLine>,%s,%s\r\n", currentcf, tmpptr2);
903#endif
904 configfilecount++;
905 }
906
907 }
908 /* Update SET variables */
909 if(strlen(INSTALLER_SETS)>0)
910 {
911 strcpy(temp, INSTALLER_SETS);
912 argn=0;
913 arg1=&temp[0];
914 arg2=arg3=NULL;
915 for(z=0;z<strlen(INSTALLER_SETS);z++)
916 {
917 if(temp[z]==',')
918 {
919 argn++;
920 temp[z]=0;
921 switch(argn)
922 {
923 case 1:
924 arg2=&temp[z+1];
925 break;
926 case 2:
927 arg3=&temp[z+1];
928 break;
929 case 3:
930 argn=0;
931 updateset(arg1, arg2, (int)(arg3[0]-'0'));
932 arg1=&temp[z+1];
933 arg2=arg3=NULL;
934 break;
935 }
936 }
937 }
938 if(arg3)
939 updateset(arg1, arg2, (int)arg3-'0');
940 }
941 /* Update system variables */
942 if(strlen(INSTALLER_SYSVAR)>0)
943 {
944 strcpy(temp, INSTALLER_SYSVAR);
945 argn=0;
946 arg1=&temp[0];
947 arg2=NULL;
948 for(z=0;z<strlen(INSTALLER_SYSVAR);z++)
949 {
950 if(temp[z]==',')
951 {
952 argn++;
953 temp[z]=0;
954 switch(argn)
955 {
956 case 1:
957 arg2=&temp[z+1];
958 break;
959 case 2:
960 argn=0;
961 updatesys(arg1, arg2);
962 arg1=&temp[z+1];
963 arg2=NULL;
964 break;
965 }
966 }
967 }
968 if(arg2)
969 updatesys(arg1, arg2);
970 }
971
972 writeconfigfile(csfile, bufile);
973}
974
975/*
976 * Reads a line from a file and returns it in raw.
977 */
978void getline(FILE *f, char *raw)
979{
980 memset(raw, 0, 256);
981 fgets(raw, 255, f);
982 stripcrlf(raw);
983}
984
985/*
986 * Removes a character from a buffer by advancing the buffer to the left.
987 */
988void removechar(char *buffer, int thisone, int len)
989{
990 int x;
991
992 for(x=thisone;x<len;x++)
993 buffer[x] = buffer[x+1];
994}
995
996/*
997 * Breaks up a line in raw into it's components.
998 */
999void parseline(char *raw, char comment, char delimiter, char quotes, char *entry, char *entrydata, char *entrydata2)
1000{
1001 char in[256];
1002 int z, len, in_quotes = 0, entrynum=0, last = 0;
1003
1004 strcpy(entry, empty_string);
1005 strcpy(entrydata, empty_string);
1006 strcpy(entrydata2, empty_string);
1007 strcpy(in, raw);
1008
1009 if(in[strlen(in)-1] == '\n')
1010 in[strlen(in)-1] = 0;
1011
1012 if(in[0] != comment)
1013 {
1014 len=strlen(in);
1015 for(z=0;z<len;z++)
1016 {
1017 if(!in_quotes && in[z] == delimiter)
1018 {
1019 in[z] = 0;
1020 /* Strip any other delimiters */
1021 z++;
1022 while(in[z] == delimiter && z < len)
1023 z++;
1024 if(!entrynum)
1025 strcpy(entry, in);
1026 else
1027 {
1028 strcpy(entrydata, &in[last]);
1029 strcpy(entrydata2, &in[z]);
1030 }
1031 last = z;
1032 if(entrynum)
1033 return;
1034 entrynum++;
1035 }
1036 if(in[z] == quotes)
1037 {
1038 removechar(in, z, len);
1039 z--;
1040 len--;
1041 if(in_quotes)
1042 in_quotes = 0;
1043 else
1044 in_quotes = 1;
1045 }
1046 }
1047 if(!entrynum)
1048 strcpy(entry, in);
1049 else
1050 strcpy(entrydata, &in[last]);
1051 }
1052}
1053
1054/*
1055 * Reads a line from the file and splits it up into it's components.
1056 */
1057int getparseline(FILE *f, char comment, char delimiter, char quotes, char *raw, char *entry, char *entrydata, char *entrydata2)
1058{
1059 getline(f, raw);
1060 parseline(raw, comment, delimiter, quotes, entry, entrydata, entrydata2);
1061 return strlen(raw);
1062}
1063
1064
1065void install_init(char *installername)
1066{
1067 if((self = fopen(installername, "rb")) == NULL)
1068 {
1069 mesg("Could not open SFX archive for reading!");
1070 exit(1);
1071 }
1072 if(loadheader() == FALSE)
1073 {
1074 mesg("Could not load all required variables!");
1075 exit(3);
1076 }
1077
1078 strcpy(installdir, INSTALLER_PATH);
1079}
1080
1081