]>
Commit | Line | Data |
---|---|---|
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 */ | |
24 | char tempPath[MAX_PATH]; | |
25 | int installstate = NONE; | |
26 | int installstage = 0; | |
27 | int current_file=0, success=0; | |
28 | unsigned long int acepos=0, aceoffset=0; | |
29 | int pixels=0; | |
30 | char confirmstring[1024]; | |
31 | /* I know I am being excessive but... better safe than sorry ;) */ | |
32 | char *configsys[8196]; | |
33 | int configfilecount=-1; | |
34 | int files = 0, files_deleted=0, packagesize=0, packagesselected[20]; | |
35 | /* Global flags often set by the user */ | |
36 | int driveselected, packagechosen, express = 1, driverstatus = -1, no_update = 0; | |
37 | int licensechecked = 0, custom = 0, checkforupdate = 1, downloadsite = 0; | |
38 | int usescitech = 1, usecurrent = 0, checking = 0, checkerror = 0, newerver = 0; | |
39 | char sddfilename[256] = "", sddversion[256] = "", sdddate[256] = ""; | |
40 | char sddurl[4][256] = { "", "", "", "" }; | |
41 | ||
42 | /* So these are accessible to REXX */ | |
43 | int drivelist[26]; | |
44 | FILE *self; | |
45 | ||
46 | /* These get loaded in loadheader */ | |
47 | char *INSTALLER_APPLICATION; | |
48 | char *INSTALLER_VERSION; | |
49 | char *INSTALLER_TITLE; | |
50 | char *INSTALLER_PATH; | |
51 | char *INSTALLER_FOLDER; | |
52 | char *INSTALLER_PROGRAM; | |
53 | char *INSTALLER_SHADOW; | |
54 | char *INSTALLER_OBJECT; | |
55 | char *INSTALLER_SETS; | |
56 | char *INSTALLER_SYSVAR; | |
57 | char *INSTALLER_SYSLINE; | |
58 | char *INSTALLER_PACKAGES[20]; | |
59 | char *INSTALLER_CONFIRM_WPS; | |
60 | char *INSTALLER_CONFIRM_CONFIGSYS; | |
61 | char *INSTALLER_CONFIRM_OVERWRITE; | |
62 | int 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) */ | |
68 | char csfile[] = "C:\\CONFIG.SYS"; | |
69 | /* Backup Config.Sys filename */ | |
70 | char bufile[] = "C:\\CONFIG.SDD"; | |
71 | /* Installation Log Database -- Used for uninstallation and aborting */ | |
72 | #if defined(__OS2__) || defined(__EMX__) || defined(WINNT) || defined(WIN32) | |
73 | char instlog[] = "C:\\DBINST.LOG"; | |
74 | #else | |
75 | char instlog[] = "~/dbinst.log"; | |
76 | #endif | |
77 | char installdir[400]; | |
78 | ||
79 | char bootdrive[2] = "C"; | |
80 | char winpath[400] = "C:\\OS2\\MDOS\\WINOS2"; | |
81 | char winjpath[400] = "C:\\OS2\\MDOS\\WINJOS2"; | |
82 | char wintpath[400] = "C:\\OS2\\MDOS\\WINTOS2"; | |
83 | char winhpath[400] = "C:\\OS2\\MDOS\\WINHOS2"; | |
84 | char browsedir[400] = "C:\\"; | |
85 | char installdir2[400] = ""; | |
86 | char empty_string[] = ""; | |
87 | char currentcf[400] = ""; | |
88 | ||
89 | #ifdef ENABLE_LOGGING | |
90 | FILE *logfile; | |
91 | #endif | |
92 | ||
93 | /* Function prototypes */ | |
94 | int installer_unpack(char *filename, int operation); | |
95 | void resetglobals(void); | |
96 | ||
97 | typedef struct _replacements { | |
98 | char *replacestring, *replacevar; | |
99 | } Replacements; | |
100 | ||
101 | /* The variables in this array must be static buffers */ | |
102 | Replacements 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 | }; | |
120 | int replacemax = 16; | |
121 | ||
122 | /* In str1, str2 gets replaced by str3 */ | |
123 | char *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 */ | |
150 | char *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 | */ | |
168 | int 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 | */ | |
219 | int 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 | */ | |
312 | int 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 | ||
325 | off_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 | ||
340 | int aceopen(const char *path, int flags) | |
341 | { | |
342 | fseek(self, aceoffset, SEEK_SET); | |
343 | return 1; | |
344 | } | |
345 | ||
346 | int aceclose(int fd) | |
347 | { | |
348 | fseek(self, aceoffset, SEEK_SET); | |
349 | return 0; | |
350 | } | |
351 | ||
352 | int acesize(void) | |
353 | { | |
354 | return packagesize; | |
355 | } | |
356 | ||
357 | int acetell(int fd) | |
358 | { | |
359 | return ftell(self)-aceoffset; | |
360 | } | |
361 | ||
362 | /* | |
363 | * Read the generated log file and remove any files installed. | |
364 | */ | |
365 | void 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 | */ | |
424 | int 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 | */ | |
456 | int 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 | */ | |
489 | void 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 | */ | |
565 | void 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 | */ | |
645 | void 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 | |
670 | MRESULT 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 | */ | |
713 | int 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 | */ | |
731 | void 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 | */ | |
745 | void 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 | */ | |
858 | void 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 | */ | |
978 | void 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 | */ | |
988 | void 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 | */ | |
999 | void 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 | */ | |
1057 | int 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 | ||
1065 | void 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 |