]>
Commit | Line | Data |
---|---|---|
853b9e91 CF |
1 | #include <windows.h> |
2 | #include <wininet.h> | |
3 | #include <assert.h> | |
ea615d51 | 4 | #include <ctype.h> |
853b9e91 CF |
5 | #include <direct.h> |
6 | #include <errno.h> | |
7 | #include <fcntl.h> | |
8 | #include <io.h> | |
9 | #include <shellapi.h> | |
10 | #include <shlguid.h> | |
11 | #include <shlobj.h> | |
12 | #include <stdio.h> | |
13 | #include <time.h> | |
14 | #include <sys/types.h> | |
15 | #include <sys/stat.h> | |
16 | ||
853b9e91 CF |
17 | #include "setup.h" |
18 | #include "strarry.h" | |
d6ef1f8f | 19 | #include "zlib/zlib.h" |
853b9e91 CF |
20 | |
21 | #define CYGNUS_KEY "Software\\Cygnus Solutions" | |
22 | #define DEF_ROOT "C:\\cygwin" | |
ea615d51 RP |
23 | #define DOWNLOAD_SUBDIR "latest" |
24 | #define SCREEN_LINES 25 | |
25 | #define COMMAND9X "command.com /E:4096 /c " | |
26 | ||
20904de1 CF |
27 | #ifndef NFILE_LIST |
28 | #define NFILE_LIST 10000 | |
29 | #endif | |
30 | ||
68cdfc92 CF |
31 | #ifndef NFILE_SLOP |
32 | #define NFILE_SLOP 20 | |
33 | #endif | |
34 | ||
ea615d51 | 35 | char *wd; |
93014d67 CF |
36 | |
37 | int downloaddir (HINTERNET session, const char *url); | |
ea615d51 | 38 | |
20904de1 | 39 | static SA files = {NULL, 0, 0}; |
93014d67 | 40 | |
853b9e91 CF |
41 | int |
42 | create_shortcut (const char *target, const char *shortcut) | |
93014d67 | 43 | { |
608de931 CF |
44 | HRESULT hres; |
45 | IShellLink *sl; | |
ea615d51 | 46 | char *path, *args; |
853b9e91 | 47 | |
608de931 CF |
48 | if (!SUCCEEDED (CoInitialize (NULL))) |
49 | return 0; | |
853b9e91 | 50 | |
608de931 | 51 | hres = |
853b9e91 | 52 | CoCreateInstance (&CLSID_ShellLink, NULL, |
ea615d51 | 53 | CLSCTX_INPROC_SERVER, &IID_IShellLink, (LPVOID *) & sl); |
608de931 | 54 | if (SUCCEEDED (hres)) |
93014d67 | 55 | { |
608de931 | 56 | IPersistFile *pf; |
ea615d51 RP |
57 | int quoted = 0; |
58 | char *c; | |
59 | ||
60 | /* Get the command only. */ | |
61 | path = xstrdup (target); | |
62 | for (c = path; quoted || (*c != ' ' && *c); ++c) | |
63 | { | |
64 | if (*c == '\"') | |
65 | quoted = !quoted; | |
66 | } | |
67 | if (*c) | |
68 | { | |
69 | *c = '\0'; | |
70 | args = c + 1; | |
71 | } | |
72 | else | |
73 | args = ""; | |
853b9e91 | 74 | |
ea615d51 RP |
75 | sl->lpVtbl->SetPath (sl, path); |
76 | sl->lpVtbl->SetArguments (sl, args); | |
77 | xfree (path); | |
853b9e91 | 78 | |
608de931 | 79 | hres = sl->lpVtbl->QueryInterface (sl, &IID_IPersistFile, &pf); |
93014d67 | 80 | |
608de931 | 81 | if (SUCCEEDED (hres)) |
93014d67 | 82 | { |
608de931 | 83 | WCHAR widepath[_MAX_PATH]; |
853b9e91 | 84 | |
608de931 CF |
85 | // Ensure that the string is Unicode. |
86 | MultiByteToWideChar (CP_ACP, 0, shortcut, -1, widepath, MAX_PATH); | |
853b9e91 | 87 | |
608de931 CF |
88 | // Save the link by calling IPersistFile::Save. |
89 | hres = pf->lpVtbl->Save (pf, widepath, TRUE); | |
90 | pf->lpVtbl->Release (pf); | |
91 | } | |
92 | sl->lpVtbl->Release (sl); | |
93 | } | |
853b9e91 | 94 | |
608de931 | 95 | CoUninitialize (); |
853b9e91 | 96 | |
608de931 | 97 | return SUCCEEDED (hres); |
93014d67 | 98 | } |
853b9e91 | 99 | |
93014d67 | 100 | |
853b9e91 CF |
101 | BOOL CALLBACK |
102 | output_file (HMODULE h, LPCTSTR type, LPTSTR name, LONG lparam) | |
93014d67 | 103 | { |
608de931 CF |
104 | HRSRC rsrc; |
105 | HGLOBAL res; | |
106 | char *data; | |
107 | FILE *out; | |
108 | BOOL retval = FALSE; | |
109 | ||
110 | size_t bytes_needed; | |
111 | if ((rsrc = FindResource (NULL, name, "FILE")) | |
112 | && (res = LoadResource (NULL, rsrc)) | |
20904de1 | 113 | && (data = (char *) LockResource (res)) && (out = fopen (strlwr (name), "w+b"))) |
608de931 CF |
114 | { |
115 | gzFile gzf; | |
116 | char *buffer; | |
117 | size_t bytes = SizeofResource (NULL, rsrc); | |
853b9e91 | 118 | |
608de931 CF |
119 | if (bytes != fwrite (data, 1, bytes, out)) |
120 | printf ("Unable to write %s: %s", name, _strerror ("")); | |
853b9e91 | 121 | |
608de931 CF |
122 | bytes_needed = *(int *) ((char *) data + bytes - sizeof (int)); |
123 | buffer = (char *) xmalloc (bytes_needed); | |
853b9e91 | 124 | |
608de931 CF |
125 | rewind (out); |
126 | gzf = gzdopen (_dup (fileno (out)), "rb"); | |
127 | if (gzf && (size_t) gzread (gzf, buffer, bytes_needed) == bytes_needed) | |
128 | { | |
129 | gzclose (gzf); | |
130 | if (fseek (out, 0, SEEK_SET) | |
131 | || fwrite (buffer, 1, bytes_needed, out) != bytes_needed) | |
132 | { | |
133 | printf ("Unable to write decompressed file to %s: %s", | |
ea615d51 | 134 | name, _strerror ("")); |
608de931 CF |
135 | } |
136 | else | |
137 | retval = TRUE; | |
138 | } | |
139 | else | |
140 | { | |
141 | int errnum; | |
142 | const char *msg = gzerror (gzf, &errnum); | |
143 | printf ("bytes_needed = %d, ", bytes_needed); | |
144 | printf ("Unable to decompress %s: Error #%d, %s\n", name, | |
ea615d51 | 145 | errnum, msg); |
608de931 CF |
146 | } |
147 | xfree (buffer); | |
148 | fclose (out); | |
149 | } | |
150 | else | |
151 | { | |
152 | printf ("Unable to write %s: %s", name, _strerror ("")); | |
153 | } | |
93014d67 | 154 | |
608de931 CF |
155 | return retval; |
156 | } | |
853b9e91 | 157 | |
20904de1 CF |
158 | static int |
159 | tarx (const char *dir, const char *fn, FILE *logfp) | |
160 | { | |
161 | char *path, *dpath; | |
162 | char buffer0[2049]; | |
163 | char *buffer = buffer0 + 1; | |
164 | int hpipe[2]; | |
165 | HANDLE hin; | |
166 | FILE *fp; | |
c73320de | 167 | int filehere; |
20904de1 CF |
168 | |
169 | dpath = pathcat (dir, fn); | |
170 | path = dtoupath (dpath); | |
171 | sprintf (buffer, "tar xvfUz \"%s\"", path); | |
172 | xfree (path); | |
173 | xfree (dpath); | |
174 | ||
175 | printf ("Installing %s\n", fn); | |
176 | ||
177 | if (_pipe (hpipe, 256, O_TEXT) == -1) | |
178 | return 0; | |
179 | ||
180 | hin = (HANDLE) _get_osfhandle (hpipe[1]); | |
181 | if (xcreate_process (0, NULL, hin, hin, buffer) == 0) | |
182 | { | |
183 | printf ("Unable to extract \"%s\": %s", fn, _strerror ("")); | |
184 | return 0; | |
185 | } | |
186 | _close (hpipe[1]); | |
187 | fp = fdopen (hpipe[0], "rt"); | |
188 | ||
c73320de | 189 | filehere = files.index; |
20904de1 CF |
190 | while (fgets (buffer, sizeof (buffer0), fp)) |
191 | { | |
192 | char *s = strchr (buffer, '\n'); | |
193 | ||
194 | if (s) | |
195 | *s = '\0'; | |
196 | ||
197 | if (strchr (buffer, ':') != NULL) | |
198 | { | |
199 | s = buffer; | |
6185466b | 200 | fprintf (stderr, "%s\n", s); |
20904de1 CF |
201 | } |
202 | else | |
203 | { | |
204 | if (++files.index >= files.count) | |
205 | files.array = realloc (files.array, | |
68cdfc92 | 206 | NFILE_SLOP + (files.count += NFILE_LIST)); |
20904de1 CF |
207 | s = buffer; |
208 | if (*s != '/') | |
209 | *--s = '/'; | |
210 | s = files.array[files.index] = utodpath (s); | |
20904de1 CF |
211 | } |
212 | ||
213 | fprintf (logfp, "%s\n", s); | |
214 | } | |
215 | fclose (fp); | |
c73320de CF |
216 | |
217 | while (++filehere <= files.index) | |
218 | (void) chmod (files.array[files.index], 0777); | |
219 | ||
20904de1 CF |
220 | return 1; |
221 | } | |
222 | ||
608de931 | 223 | int |
20904de1 | 224 | recurse_dirs (const char *dir, FILE *logfp) |
608de931 CF |
225 | { |
226 | int err = 0; | |
227 | int retval = 0; | |
853b9e91 | 228 | |
608de931 CF |
229 | char *pattern = pathcat (dir, "*"); |
230 | if (pattern) | |
231 | { | |
232 | WIN32_FIND_DATA find_data; | |
233 | HANDLE handle; | |
853b9e91 | 234 | |
608de931 CF |
235 | handle = FindFirstFile (pattern, &find_data); |
236 | if (handle != INVALID_HANDLE_VALUE) | |
237 | { | |
238 | /* Recurse through all subdirectories */ | |
239 | do | |
240 | { | |
241 | if (strcmp (find_data.cFileName, ".") == 0 | |
242 | || strcmp (find_data.cFileName, "..") == 0) | |
243 | continue; | |
853b9e91 | 244 | |
608de931 | 245 | if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY |
ea615d51 | 246 | /* && strlen(find_data.cFileName) */ ) |
608de931 CF |
247 | { |
248 | char *subdir = pathcat (dir, find_data.cFileName); | |
249 | if (subdir) | |
250 | { | |
20904de1 | 251 | if (!recurse_dirs (subdir, logfp)) |
608de931 CF |
252 | { |
253 | xfree (subdir); | |
254 | err = 1; | |
255 | break; | |
256 | } | |
853b9e91 | 257 | |
608de931 CF |
258 | xfree (subdir); |
259 | } | |
260 | else | |
261 | lowmem (); | |
262 | } | |
263 | } | |
264 | while (FindNextFile (handle, &find_data) && !err); | |
265 | FindClose (handle); | |
266 | ||
267 | /* Look for .tar.gz files */ | |
268 | if (!err) | |
93014d67 | 269 | { |
608de931 CF |
270 | xfree (pattern); |
271 | pattern = pathcat (dir, "*.tar.gz"); | |
272 | handle = FindFirstFile (pattern, &find_data); | |
273 | if (handle != INVALID_HANDLE_VALUE) | |
274 | { | |
275 | int err = 0; | |
853b9e91 | 276 | |
608de931 CF |
277 | do |
278 | { | |
608de931 CF |
279 | /* Skip source archives and meta-directories */ |
280 | if (strstr (find_data.cFileName, "-src.tar.gz") | |
281 | || strstr (find_data.cFileName, "-src-") | |
282 | || strcmp (find_data.cFileName, ".") == 0 | |
283 | || strcmp (find_data.cFileName, "..") == 0) | |
284 | { | |
285 | continue; | |
286 | } | |
287 | ||
20904de1 | 288 | if (!tarx (dir, find_data.cFileName, logfp)) |
608de931 | 289 | { |
608de931 CF |
290 | err = 1; |
291 | break; | |
292 | } | |
293 | } | |
294 | while (FindNextFile (handle, &find_data)); | |
295 | FindClose (handle); | |
296 | } | |
297 | if (!err) | |
298 | retval = 1; | |
299 | } | |
300 | } | |
301 | ||
302 | xfree (pattern); | |
303 | } | |
304 | else | |
305 | lowmem (); | |
853b9e91 | 306 | |
608de931 | 307 | return retval; |
93014d67 | 308 | } |
853b9e91 | 309 | |
853b9e91 | 310 | |
608de931 | 311 | void |
ea615d51 | 312 | setpath (const char *element) |
608de931 | 313 | { |
ea615d51 | 314 | char *buffer = xmalloc (strlen (element) + 7); |
853b9e91 | 315 | |
ea615d51 | 316 | sprintf (buffer, "PATH=%s", element); |
608de931 | 317 | putenv (buffer); |
853b9e91 | 318 | |
608de931 CF |
319 | xfree (buffer); |
320 | } | |
853b9e91 | 321 | |
608de931 CF |
322 | char * |
323 | prompt (const char *text, const char *def) | |
324 | { | |
325 | char buffer[_MAX_PATH]; | |
853b9e91 | 326 | |
853b9e91 | 327 | |
608de931 CF |
328 | printf ((def ? "%s? [%s] " : "%s? "), text, def); |
329 | fgets (buffer, sizeof (buffer), stdin); | |
330 | buffer[strcspn (buffer, "\r\n")] = '\0'; | |
853b9e91 | 331 | |
608de931 CF |
332 | /* Duplicate the entered value or the default if nothing was entered. */ |
333 | return xstrdup (strlen (buffer) ? buffer : def ? def : ""); | |
93014d67 | 334 | } |
853b9e91 | 335 | |
608de931 CF |
336 | int |
337 | optionprompt (const char *text, SA * options) | |
338 | { | |
ea615d51 | 339 | size_t n, lbound, response; |
608de931 | 340 | char buf[5]; |
853b9e91 | 341 | |
ea615d51 | 342 | n = 0; |
853b9e91 | 343 | |
608de931 | 344 | do |
93014d67 | 345 | { |
ea615d51 RP |
346 | char *or; |
347 | size_t base = n; | |
348 | enum | |
349 | { CONTINUE, REPEAT, ALL } | |
350 | mode; | |
351 | ||
352 | if (!base) | |
353 | puts (text); | |
354 | ||
355 | for (n = 0; n < base + SCREEN_LINES - 2 && n < options->count; ++n) | |
356 | printf ("\t%d. %s\n", n + 1, options->array[n]); | |
357 | ||
358 | lbound = n - (SCREEN_LINES - (base ? 2 : 3)); | |
359 | if (n < options->count) | |
360 | { | |
361 | mode = CONTINUE; | |
362 | or = " or [continue]"; | |
363 | } | |
364 | else if (options->count > SCREEN_LINES - 2) | |
365 | { | |
366 | mode = REPEAT; | |
367 | or = " or [repeat]"; | |
368 | } | |
369 | else | |
370 | { | |
371 | mode = ALL; | |
372 | or = ""; | |
373 | } | |
374 | printf ("Select an option from %d-%d%s: ", lbound, n, or); | |
608de931 CF |
375 | if (!fgets (buf, sizeof (buf), stdin)) |
376 | continue; | |
853b9e91 | 377 | |
ea615d51 RP |
378 | if (mode == CONTINUE && (!isalnum (*buf) || strchr ("cC", *buf))) |
379 | continue; | |
380 | else if (mode == REPEAT && (!isalnum (*buf) || strchr ("rR", *buf))) | |
381 | { | |
382 | n = 0; | |
383 | continue; | |
384 | } | |
385 | ||
608de931 CF |
386 | response = atoi (buf); |
387 | } | |
ea615d51 | 388 | while (response < lbound || response > n); |
853b9e91 | 389 | |
608de931 | 390 | return response - 1; |
93014d67 | 391 | } |
853b9e91 | 392 | |
608de931 | 393 | int |
6f8e3b45 | 394 | geturl (HINTERNET session, const char *url, const char *file, int verbose) |
608de931 CF |
395 | { |
396 | DWORD type, size; | |
397 | int authenticated = 0; | |
398 | int retval = 0; | |
399 | HINTERNET connect; | |
6f8e3b45 | 400 | int tries = 20; |
93014d67 | 401 | |
6f8e3b45 CF |
402 | if (verbose) |
403 | { | |
404 | printf ("Connecting to ftp site..."); | |
405 | fflush (stdout); | |
406 | } | |
407 | for (tries = 1; tries <= 20; tries++) | |
608de931 CF |
408 | { |
409 | connect = | |
410 | InternetOpenUrl (session, url, NULL, 0, | |
411 | INTERNET_FLAG_DONT_CACHE | | |
412 | INTERNET_FLAG_KEEP_CONNECTION | | |
413 | INTERNET_FLAG_RELOAD, 0); | |
6f8e3b45 CF |
414 | if (connect) |
415 | break; | |
416 | if (!verbose || tries == 1) | |
417 | /* nothing */; | |
418 | else if (tries > 2) | |
419 | printf ("\rConnecting to ftp site...(try %d) \b\b", tries); | |
420 | else | |
421 | printf ("\rConnecting to ftp site...(try %d)", tries); | |
608de931 | 422 | } |
608de931 CF |
423 | |
424 | if (!connect) | |
6f8e3b45 CF |
425 | { |
426 | puts ("\nCouldn't connect to ftp site."); fflush (stdout); | |
427 | winerror (); | |
428 | } | |
608de931 | 429 | else |
6f8e3b45 CF |
430 | { |
431 | if (verbose) | |
432 | { | |
433 | if (tries > 1) | |
434 | printf ("\rConnecting to ftp site... \b\b\b\b\b\b\b\b"); | |
435 | printf ("Done.\n"); fflush (stdout); | |
436 | } | |
437 | while (!authenticated) | |
438 | { | |
439 | size = sizeof (type); | |
440 | if (!InternetQueryOption | |
441 | (connect, INTERNET_OPTION_HANDLE_TYPE, &type, &size)) | |
608de931 | 442 | { |
6f8e3b45 CF |
443 | winerror (); |
444 | return 0; | |
445 | } | |
446 | else | |
447 | switch (type) | |
448 | { | |
449 | case INTERNET_HANDLE_TYPE_HTTP_REQUEST: | |
450 | case INTERNET_HANDLE_TYPE_CONNECT_HTTP: | |
451 | size = sizeof (DWORD); | |
452 | if (!HttpQueryInfo | |
453 | (connect, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, | |
454 | &type, &size, NULL)) | |
455 | { | |
456 | winerror (); | |
457 | return 0; | |
458 | } | |
459 | else if (type == HTTP_STATUS_PROXY_AUTH_REQ) | |
460 | { | |
461 | DWORD len; | |
93014d67 | 462 | |
6f8e3b45 CF |
463 | if (!InternetQueryDataAvailable (connect, &len, 0, 0)) |
464 | { | |
465 | winerror (); | |
466 | return 0; | |
467 | } | |
468 | else | |
469 | { | |
470 | char *user, *password; | |
471 | ||
472 | /* Have to read any pending data, WININET peculiarity. */ | |
473 | char *buffer = xmalloc (len); | |
474 | do | |
475 | { | |
476 | InternetReadFile (connect, buffer, len, &size); | |
477 | } | |
478 | while (size); | |
479 | xfree (buffer); | |
480 | ||
481 | puts ("Proxy authentication is required.\n"); | |
482 | ||
483 | user = prompt ("Proxy username", NULL); | |
484 | if (!InternetSetOption | |
485 | (connect, INTERNET_OPTION_PROXY_USERNAME, user, | |
486 | strlen (user))) | |
487 | { | |
488 | xfree (user); | |
489 | winerror (); | |
490 | return 0; | |
491 | } | |
492 | else | |
493 | { | |
494 | xfree (user); | |
495 | password = prompt ("Proxy password", NULL); | |
496 | if (!InternetSetOption | |
497 | (connect, INTERNET_OPTION_PROXY_PASSWORD, | |
498 | password, | |
499 | strlen (password)) | |
500 | || !HttpSendRequest (connect, NULL, 0, NULL, 0)) | |
501 | { | |
502 | xfree (password); | |
503 | winerror (); | |
504 | return 0; | |
505 | } | |
506 | xfree (password); | |
507 | } | |
508 | } | |
509 | } | |
510 | else if (type != HTTP_STATUS_OK) | |
511 | { | |
512 | printf ("Error retrieving \"%s\".\n", url); | |
513 | return 0; | |
514 | } | |
515 | else | |
516 | authenticated = 1; | |
517 | break; | |
93014d67 | 518 | |
6f8e3b45 CF |
519 | default: |
520 | authenticated = 1; | |
521 | break; | |
522 | } | |
523 | ||
524 | /* Now that authentication is complete read the file. */ | |
525 | if (!InternetQueryDataAvailable (connect, &size, 0, 0)) | |
526 | winerror (); | |
527 | else | |
528 | { | |
529 | char *buffer = xmalloc (size); | |
93014d67 | 530 | |
6f8e3b45 CF |
531 | FILE *out = fopen (file, "wb"); |
532 | if (!out) | |
533 | printf ("Unable to open \"%s\" for output: %s\n", file, | |
534 | _strerror ("")); | |
535 | else | |
536 | { | |
537 | for (;;) | |
538 | { | |
539 | DWORD readbytes; | |
608de931 | 540 | |
6f8e3b45 CF |
541 | if (!InternetReadFile (connect, buffer, size, &readbytes)) |
542 | winerror (); | |
543 | else if (!readbytes) | |
608de931 | 544 | { |
6f8e3b45 CF |
545 | retval = 1; |
546 | break; | |
608de931 | 547 | } |
6f8e3b45 | 548 | else if (fwrite (buffer, 1, readbytes, out) != readbytes) |
608de931 | 549 | { |
6f8e3b45 CF |
550 | printf ("Error writing \"%s\": %s\n", file, |
551 | _strerror ("")); | |
552 | break; | |
608de931 CF |
553 | } |
554 | } | |
6f8e3b45 | 555 | fclose (out); |
608de931 | 556 | } |
6f8e3b45 | 557 | xfree (buffer); |
608de931 | 558 | } |
6f8e3b45 CF |
559 | InternetCloseHandle (connect); |
560 | } | |
561 | } | |
853b9e91 | 562 | |
608de931 CF |
563 | return retval; |
564 | } | |
853b9e91 | 565 | |
608de931 CF |
566 | char * |
567 | findhref (char *buffer) | |
568 | { | |
569 | char *ref = strstr (buffer, "href="); | |
853b9e91 | 570 | |
608de931 CF |
571 | if (!ref) |
572 | ref = strstr (buffer, "HREF="); | |
853b9e91 | 573 | |
608de931 | 574 | if (ref) |
93014d67 | 575 | { |
608de931 CF |
576 | int len; |
577 | ref += ref[5] == '"' ? 6 : 5; | |
853b9e91 | 578 | |
608de931 | 579 | len = strcspn (ref, "\" >"); |
853b9e91 | 580 | |
608de931 CF |
581 | ref[len] = '\0'; |
582 | } | |
853b9e91 | 583 | |
608de931 CF |
584 | return ref; |
585 | } | |
853b9e91 | 586 | |
608de931 CF |
587 | int |
588 | processdirlisting (HINTERNET session, const char *urlbase, const char *file) | |
589 | { | |
590 | int retval; | |
591 | char buffer[256]; | |
6f8e3b45 | 592 | static enum {UNKNOWN, ALWAYS, NEVER} download_when = {UNKNOWN}; |
853b9e91 | 593 | |
c1246750 | 594 | FILE *in = fopen (file, "rt"); |
853b9e91 | 595 | |
608de931 CF |
596 | while (fgets (buffer, sizeof (buffer), in)) |
597 | { | |
598 | char *ref = findhref (buffer); | |
853b9e91 | 599 | |
608de931 | 600 | if (ref) |
93014d67 | 601 | { |
608de931 CF |
602 | char url[256]; |
603 | DWORD urlspace = sizeof (url); | |
853b9e91 | 604 | |
608de931 CF |
605 | if (!InternetCombineUrl |
606 | (urlbase, ref, url, &urlspace, | |
607 | ICU_BROWSER_MODE | ICU_ENCODE_SPACES_ONLY | ICU_NO_META)) | |
608 | { | |
609 | printf ("Unable to download from %s", ref); | |
610 | winerror (); | |
611 | } | |
612 | else if (ref[strlen (ref) - 1] == '/') | |
613 | { | |
614 | if (strcmp (url + strlen (url) - 2, "./") != 0) | |
615 | downloaddir (session, url); | |
616 | } | |
617 | else if (strstr (url, ".tar.gz") && !strstr (url, "-src")) | |
618 | { | |
619 | int download = 0; | |
620 | char *filename = strrchr (url, '/') + 1; | |
36dc5fc8 | 621 | if (download_when == ALWAYS || _access (filename, 0) == -1) |
6f8e3b45 CF |
622 | download = 1; |
623 | else | |
608de931 CF |
624 | { |
625 | char text[_MAX_PATH]; | |
626 | char *answer; | |
853b9e91 | 627 | |
36dc5fc8 CF |
628 | if (download_when == NEVER) |
629 | answer = "N"; | |
630 | else | |
631 | { | |
632 | sprintf (text, "Replace %s from the net (ynAN)", filename); | |
633 | answer = prompt (text, "y"); | |
634 | } | |
853b9e91 | 635 | |
608de931 CF |
636 | if (answer) |
637 | { | |
6f8e3b45 CF |
638 | switch (*answer) |
639 | { | |
640 | case 'a': | |
641 | case 'A': | |
642 | download_when = ALWAYS; | |
35d18861 | 643 | /* purposely fall through */ |
6f8e3b45 CF |
644 | case 'y': |
645 | case 'Y': | |
646 | download = 1; | |
35d18861 | 647 | break; |
6f8e3b45 CF |
648 | case 'N': |
649 | download_when = NEVER; | |
36dc5fc8 | 650 | fprintf (stderr, "Skipping %s\n", filename); |
6f8e3b45 CF |
651 | case 'n': |
652 | default: | |
653 | download = 0; | |
654 | } | |
608de931 CF |
655 | xfree (answer); |
656 | } | |
657 | } | |
853b9e91 | 658 | |
608de931 CF |
659 | if (download) |
660 | { | |
36dc5fc8 | 661 | printf ("Downloading: %s...", filename); |
608de931 | 662 | fflush (stdout); |
6f8e3b45 | 663 | if (geturl (session, url, filename, 0)) |
608de931 CF |
664 | { |
665 | printf ("Done.\n"); | |
666 | } | |
667 | else | |
668 | { | |
6f8e3b45 | 669 | printf ("\nUnable to retrieve %s\n", url); |
608de931 CF |
670 | } |
671 | } | |
672 | } | |
673 | } | |
674 | } | |
853b9e91 | 675 | |
6f8e3b45 | 676 | fflush (stdout); |
608de931 | 677 | retval = feof (in); |
853b9e91 | 678 | |
608de931 | 679 | fclose (in); |
853b9e91 | 680 | |
608de931 | 681 | return retval; |
93014d67 | 682 | } |
853b9e91 | 683 | |
608de931 CF |
684 | char * |
685 | tmpfilename () | |
686 | { | |
687 | return xstrdup (tmpnam (NULL)); | |
93014d67 | 688 | } |
853b9e91 | 689 | |
608de931 CF |
690 | int |
691 | downloaddir (HINTERNET session, const char *url) | |
692 | { | |
693 | int retval = 0; | |
694 | char *file = tmpfilename (); | |
93014d67 | 695 | |
6f8e3b45 | 696 | if (geturl (session, url, file, 1)) |
608de931 CF |
697 | retval = processdirlisting (session, url, file); |
698 | xfree (file); | |
93014d67 | 699 | |
608de931 | 700 | return retval; |
93014d67 CF |
701 | } |
702 | ||
703 | ||
ea615d51 | 704 | HINTERNET opensession () |
93014d67 | 705 | { |
608de931 CF |
706 | return InternetOpen ("Cygwin Setup", INTERNET_OPEN_TYPE_PRECONFIG, NULL, |
707 | NULL, 0); | |
708 | } | |
853b9e91 | 709 | |
608de931 CF |
710 | int |
711 | downloadfrom (const char *url) | |
712 | { | |
713 | int retval = 0; | |
853b9e91 | 714 | |
608de931 | 715 | HINTERNET session = opensession (); |
853b9e91 | 716 | |
608de931 CF |
717 | if (!session) |
718 | winerror (); | |
719 | else | |
720 | { | |
721 | char *file = tmpfilename (); | |
853b9e91 | 722 | |
6f8e3b45 | 723 | if (geturl (session, url, file, 1)) |
608de931 | 724 | retval = processdirlisting (session, url, file); |
853b9e91 | 725 | |
608de931 | 726 | xfree (file); |
93014d67 | 727 | |
608de931 CF |
728 | InternetCloseHandle (session); |
729 | } | |
93014d67 | 730 | |
608de931 | 731 | return retval; |
93014d67 CF |
732 | } |
733 | ||
608de931 CF |
734 | int |
735 | reverse_sort (const void *arg1, const void *arg2) | |
736 | { | |
737 | return -strcmp (*(char **) arg1, *(char **) arg2); | |
738 | } | |
93014d67 | 739 | |
608de931 | 740 | int |
6f8e3b45 | 741 | create_uninstall (const char *wd, const char *folder, const char *shellscut, |
20904de1 | 742 | const char *shortcut) |
93014d67 | 743 | { |
608de931 CF |
744 | int retval = 0; |
745 | char buffer[MAX_PATH]; | |
608de931 | 746 | clock_t start; |
6f8e3b45 CF |
747 | HINSTANCE lib; |
748 | ||
20904de1 | 749 | printf ("Creating the uninstall file..."); |
608de931 | 750 | fflush (stdout); |
20904de1 | 751 | if (files.array) |
608de931 | 752 | { |
20904de1 CF |
753 | size_t n; |
754 | FILE *uninst; | |
68cdfc92 CF |
755 | char cwd[MAX_PATH]; |
756 | char *uninstfile; | |
853b9e91 | 757 | |
68cdfc92 CF |
758 | getcwd (cwd, sizeof (cwd)); |
759 | uninstfile = pathcat (cwd, "uninst.bat"); | |
760 | uninst = fopen (uninstfile, "wt"); | |
853b9e91 | 761 | |
20904de1 CF |
762 | if (uninst) |
763 | { | |
20904de1 | 764 | unsigned percent = 0; |
68cdfc92 CF |
765 | struct _stat st; |
766 | ||
767 | files.array[++files.index] = pathcat (cwd, "bin\\cygwin.bat"); | |
768 | files.count = files.index + 1; | |
769 | qsort (files.array, files.count, sizeof (char *), reverse_sort); | |
20904de1 | 770 | |
20904de1 CF |
771 | fprintf (uninst, |
772 | "@echo off\n" "%c:\n" "cd \"%s\"\n", *cwd, cwd); | |
773 | for (n = 0; n < files.count; ++n) | |
608de931 | 774 | { |
20904de1 | 775 | char *dpath; |
93014d67 | 776 | |
20904de1 CF |
777 | if (n && !strcmp (files.array[n], files.array[n - 1])) |
778 | continue; | |
93014d67 | 779 | |
20904de1 | 780 | dpath = files.array[n]; |
93014d67 | 781 | |
68cdfc92 | 782 | if (_stat (dpath, &st) == 0 && st.st_mode & _S_IFDIR) |
20904de1 CF |
783 | fprintf (uninst, "rmdir \"%s\"\n", dpath); |
784 | else | |
608de931 | 785 | { |
20904de1 CF |
786 | if (access (dpath, 6) != 0) |
787 | fprintf (uninst, "attrib -r \"%s\"\n", dpath); | |
788 | fprintf (uninst, "del \"%s\"\n", dpath); | |
608de931 CF |
789 | } |
790 | } | |
20904de1 CF |
791 | fprintf (uninst, |
792 | "del \"%s\"\n" | |
793 | "del \"%s\"\n" | |
794 | "rmdir \"%s\"\n" | |
68cdfc92 CF |
795 | "del %s\n", shortcut, shellscut, |
796 | folder, uninstfile); | |
20904de1 CF |
797 | fclose (uninst); |
798 | ||
68cdfc92 | 799 | create_shortcut (uninstfile, shortcut); |
608de931 | 800 | } |
20904de1 CF |
801 | sa_cleanup (&files); |
802 | retval = 1; | |
608de931 | 803 | } |
853b9e91 | 804 | |
608de931 CF |
805 | if (lib) |
806 | FreeLibrary (lib); | |
853b9e91 | 807 | |
ade98143 | 808 | printf ("Done.\n"); |
608de931 CF |
809 | return retval; |
810 | } | |
853b9e91 | 811 | |
93014d67 | 812 | |
608de931 CF |
813 | /* Writes the startup batch file. */ |
814 | int | |
20904de1 | 815 | do_start_menu (const char *root) |
608de931 CF |
816 | { |
817 | FILE *batch; | |
6f8e3b45 | 818 | char *batch_name = pathcat (root, "bin\\cygwin.bat"); |
608de931 | 819 | int retval = 0; |
853b9e91 | 820 | |
608de931 CF |
821 | /* Create the batch file for the start menu. */ |
822 | if (batch_name) | |
823 | { | |
c1246750 | 824 | batch = fopen (batch_name, "wt"); |
608de931 CF |
825 | if (batch) |
826 | { | |
827 | LPITEMIDLIST progfiles; | |
828 | char pfilespath[_MAX_PATH]; | |
829 | char *folder; | |
830 | ||
831 | fprintf (batch, | |
832 | "@echo off\n" | |
4b40edd0 | 833 | "SET MAKE_MODE=unix\n" |
68cdfc92 | 834 | "SET PATH=%s\\bin;%s\\usr\\local\\bin;%%PATH%%\n" |
608de931 CF |
835 | "bash\n", root, root); |
836 | fclose (batch); | |
837 | ||
838 | /* Create a shortcut to the batch file */ | |
839 | SHGetSpecialFolderLocation (NULL, CSIDL_PROGRAMS, &progfiles); | |
840 | SHGetPathFromIDList (progfiles, pfilespath); | |
841 | ||
842 | folder = pathcat (pfilespath, "Cygnus Solutions"); | |
843 | if (folder) | |
844 | { | |
845 | char *shortcut; | |
846 | mkdir (folder); /* Ignore the result, it may exist. */ | |
853b9e91 | 847 | |
608de931 CF |
848 | shortcut = pathcat (folder, "Cygwin 1.1.0.lnk"); |
849 | if (shortcut) | |
850 | { | |
ea615d51 RP |
851 | char *cmdline; |
852 | OSVERSIONINFO verinfo; | |
853 | verinfo.dwOSVersionInfoSize = sizeof (verinfo); | |
854 | ||
855 | /* If we are running Win9x, build a command line. */ | |
856 | GetVersionEx (&verinfo); | |
857 | if (verinfo.dwPlatformId == VER_PLATFORM_WIN32_NT) | |
858 | cmdline = xstrdup (batch_name); | |
859 | else | |
860 | { | |
861 | char *pccmd; | |
862 | char windir[MAX_PATH]; | |
863 | GetWindowsDirectory (windir, sizeof (windir)); | |
864 | ||
865 | pccmd = pathcat (windir, COMMAND9X); | |
866 | cmdline = | |
867 | xmalloc (strlen (pccmd) + strlen (batch_name) + 1); | |
868 | strcat (strcpy (cmdline, pccmd), batch_name); | |
869 | xfree (pccmd); | |
870 | } | |
871 | ||
872 | if (create_shortcut (cmdline, shortcut)) | |
608de931 CF |
873 | { |
874 | char *uninstscut = | |
ea615d51 | 875 | pathcat (folder, "Uninstall Cygwin 1.1.0.lnk"); |
608de931 CF |
876 | if (uninstscut) |
877 | { | |
878 | if (create_uninstall | |
20904de1 | 879 | (wd, folder, shortcut, uninstscut)) |
608de931 CF |
880 | retval = 1; |
881 | xfree (uninstscut); | |
882 | } | |
883 | } | |
ea615d51 | 884 | xfree (cmdline); |
608de931 CF |
885 | xfree (shortcut); |
886 | } | |
887 | xfree (folder); | |
888 | } | |
889 | } | |
890 | ||
891 | xfree (batch_name); | |
892 | } | |
893 | return retval; | |
894 | } | |
853b9e91 | 895 | |
608de931 CF |
896 | char * |
897 | getdownloadsource () | |
898 | { | |
899 | char *retval = NULL; | |
900 | HINTERNET session = opensession (); | |
901 | char *filename = tmpfilename (); | |
902 | ||
903 | if (!session) | |
904 | winerror (); | |
905 | else if (!geturl | |
906 | (session, "http://sourceware.cygnus.com/cygwin/mirrors.html", | |
6f8e3b45 | 907 | filename, 1)) |
608de931 CF |
908 | fputs ("Unable to retrieve the list of cygwin mirrors.\n", stderr); |
909 | else | |
910 | { | |
c1246750 | 911 | FILE *in = fopen (filename, "rt"); |
853b9e91 | 912 | |
608de931 CF |
913 | if (!in) |
914 | fprintf (stderr, "Unable to open %s for input.\n", filename); | |
915 | else | |
916 | { | |
917 | size_t option; | |
918 | int ready4urls = 0; | |
919 | char buf[256]; | |
ea615d51 | 920 | SA urls, names; /* These must stay sync'd. */ |
853b9e91 | 921 | |
608de931 | 922 | sa_init (&urls); |
ea615d51 | 923 | sa_init (&names); |
853b9e91 | 924 | |
608de931 CF |
925 | while (fgets (buf, sizeof (buf), in)) |
926 | { | |
927 | if (!ready4urls) | |
928 | { | |
929 | if (strstr (buf, "Mirror Sites:")) | |
930 | ready4urls = 1; | |
931 | } | |
932 | else | |
933 | { | |
934 | char *ref = findhref (buf); | |
93014d67 | 935 | |
608de931 CF |
936 | if (ref) |
937 | { | |
938 | size_t len = strlen (ref); | |
853b9e91 | 939 | |
608de931 CF |
940 | if (ref[len - 1] == '/') |
941 | { | |
ea615d51 | 942 | char *name; |
608de931 CF |
943 | char *url = xmalloc (len + 13); |
944 | ||
ea615d51 | 945 | strcat (strcpy (url, ref), DOWNLOAD_SUBDIR); |
608de931 | 946 | sa_add (&urls, url); |
ea615d51 RP |
947 | |
948 | /* Get just the sites name. */ | |
949 | name = strstr (url, "//"); | |
950 | if (name) | |
951 | name += 2; | |
952 | else | |
953 | name = url; | |
954 | *strchr (name, '/') = '\0'; | |
955 | sa_add (&names, url); | |
956 | ||
608de931 CF |
957 | xfree (url); |
958 | } | |
959 | } | |
960 | } | |
961 | } | |
962 | ||
963 | sa_add (&urls, "Other"); | |
ea615d51 | 964 | sa_add (&names, "Other"); |
608de931 | 965 | option = |
ea615d51 | 966 | optionprompt ("Select a download location close to you:", &names); |
608de931 CF |
967 | if (option == urls.count - 1) |
968 | retval = prompt ("Download url", NULL); | |
969 | else | |
970 | retval = xstrdup (urls.array[option]); | |
93014d67 | 971 | |
608de931 | 972 | sa_cleanup (&urls); |
ea615d51 | 973 | sa_cleanup (&names); |
608de931 CF |
974 | } |
975 | } | |
976 | unlink (filename); | |
853b9e91 | 977 | |
608de931 CF |
978 | return retval; |
979 | } | |
853b9e91 | 980 | |
93014d67 | 981 | |
608de931 CF |
982 | /* Basically a mkdir -p /somedir function. */ |
983 | void | |
984 | mkdirp (const char *dir) | |
985 | { | |
986 | if (mkdir (dir) == -1 && errno != EEXIST) | |
987 | { | |
988 | char *parent = strdup (dir); | |
989 | char *slash = strrchr (parent, '\\'); | |
853b9e91 | 990 | |
608de931 CF |
991 | if (slash) |
992 | { | |
993 | *slash = '\0'; | |
994 | mkdirp (parent); | |
995 | } | |
93014d67 | 996 | |
608de931 | 997 | xfree (parent); |
93014d67 | 998 | |
608de931 CF |
999 | mkdir (dir); |
1000 | } | |
93014d67 CF |
1001 | } |
1002 | ||
1003 | ||
608de931 | 1004 | /* This routine assumes that the cwd is the root directory. */ |
853b9e91 | 1005 | int |
608de931 CF |
1006 | mkmount (const char *mountexedir, const char *root, const char *dospath, |
1007 | const char *unixpath, int force) | |
93014d67 | 1008 | { |
608de931 CF |
1009 | char *mount, *bslashed, *fulldospath, *p; |
1010 | char buffer[1024]; | |
853b9e91 | 1011 | |
20904de1 CF |
1012 | if (*root == '\0') |
1013 | fulldospath = xstrdup (dospath); | |
1014 | else | |
1015 | { | |
1016 | /* Make sure the mount point exists. */ | |
1017 | mount = utodpath (unixpath); | |
1018 | mkdirp (mount); | |
1019 | xfree (mount); | |
1020 | fulldospath = pathcat (root, dospath); | |
1021 | } | |
853b9e91 | 1022 | |
608de931 | 1023 | /* Make sure the target path exists. */ |
608de931 | 1024 | mkdirp (fulldospath); |
853b9e91 | 1025 | |
608de931 CF |
1026 | /* Mount the directory. */ |
1027 | mount = pathcat (mountexedir, "mount"); | |
1028 | sprintf (buffer, "%s %s -b \"%s\" %s", mount, force ? "-f" : "", | |
ea615d51 | 1029 | fulldospath, unixpath); |
608de931 CF |
1030 | xfree (mount); |
1031 | xfree (fulldospath); | |
93014d67 | 1032 | |
ea615d51 | 1033 | return xsystem (buffer) == 0; |
608de931 | 1034 | } |
853b9e91 | 1035 | |
608de931 CF |
1036 | int |
1037 | main () | |
1038 | { | |
1039 | int retval = 1; /* Default to error code */ | |
20904de1 CF |
1040 | clock_t start; |
1041 | ||
6f8e3b45 CF |
1042 | puts ( "\n\n\n\n" |
1043 | "This is the Cygwin setup utility.\n\n" | |
1044 | "Use this program to install the latest version of the Cygwin Utilities\n" | |
1045 | "from the Internet.\n\n" | |
1046 | "Alternatively, if you already have already downloaded the appropriate files\n" | |
1047 | "to the current directory, this program can use those as the basis for your\n" | |
1048 | "installation.\n"); | |
1049 | ||
20904de1 | 1050 | start = clock (); |
608de931 | 1051 | if (!EnumResourceNames (NULL, "FILE", output_file, 0)) |
93014d67 | 1052 | { |
608de931 CF |
1053 | winerror (); |
1054 | } | |
1055 | else | |
1056 | { | |
608de931 CF |
1057 | char *defroot, *update; |
1058 | char *root; | |
1059 | int done; | |
1060 | HKEY cu = NULL, lm = NULL; | |
1061 | ||
ea615d51 RP |
1062 | wd = _getcwd (NULL, 0); |
1063 | setpath (wd); | |
608de931 CF |
1064 | |
1065 | /* Begin prompting user for setup requirements. */ | |
1066 | printf ("Press <enter> to accept the default value.\n"); | |
1067 | ||
ea615d51 RP |
1068 | /* If some Cygnus software has been installed, assume there is a root |
1069 | mount in the registry. Otherwise use C:\cygwin for the default root | |
608de931 CF |
1070 | directory. */ |
1071 | if (RegOpenKey (HKEY_CURRENT_USER, CYGNUS_KEY, &cu) == ERROR_SUCCESS | |
1072 | || RegOpenKey (HKEY_LOCAL_MACHINE, CYGNUS_KEY, | |
1073 | &lm) == ERROR_SUCCESS) | |
1074 | { | |
1075 | defroot = utodpath ("/"); | |
1076 | if (cu) | |
1077 | RegCloseKey (cu); | |
1078 | if (lm) | |
1079 | RegCloseKey (lm); | |
1080 | } | |
1081 | else | |
1082 | defroot = xstrdup (DEF_ROOT); | |
853b9e91 | 1083 | |
ea615d51 | 1084 | /* Get the root directory and warn the user if there are any spaces in |
608de931 CF |
1085 | the path. */ |
1086 | for (done = 0; !done;) | |
93014d67 | 1087 | { |
608de931 CF |
1088 | root = prompt ("Root directory", defroot); |
1089 | if (strchr (root, ' ')) | |
93014d67 | 1090 | { |
608de931 CF |
1091 | char *temp; |
1092 | temp = | |
1093 | prompt | |
93014d67 | 1094 | ("Using spaces in the root directory path may cause problems." |
608de931 CF |
1095 | " Continue anyway", "no"); |
1096 | if (toupper (*temp) == 'Y') | |
1097 | done = 1; | |
1098 | xfree (temp); | |
1099 | } | |
93014d67 | 1100 | else |
608de931 CF |
1101 | done = 1; |
1102 | } | |
1103 | xfree (defroot); | |
853b9e91 | 1104 | |
608de931 CF |
1105 | /* Create the root directory. */ |
1106 | mkdir (root); /* Ignore any return value since it may | |
93014d67 | 1107 | already exist. */ |
20904de1 | 1108 | mkmount (wd, "", root, "/", 1); |
853b9e91 | 1109 | |
608de931 | 1110 | update = |
6f8e3b45 CF |
1111 | prompt ("Install from the current directory (d) or from the Internet (i)", "i"); |
1112 | if (toupper (*update) == 'I') | |
93014d67 | 1113 | { |
608de931 | 1114 | char *dir = getdownloadsource (); |
853b9e91 | 1115 | |
608de931 | 1116 | if (dir) |
93014d67 | 1117 | { |
608de931 CF |
1118 | downloadfrom (dir); |
1119 | xfree (dir); | |
1120 | } | |
1121 | } | |
1122 | xfree (update); | |
1123 | ||
ea615d51 | 1124 | /* Make the root directory the current directory so that recurse_dirs |
608de931 CF |
1125 | will * extract the packages into the correct path. */ |
1126 | if (chdir (root) == -1) | |
93014d67 | 1127 | { |
608de931 | 1128 | printf ("Unable to make \"%s\" the current directory: %s\n", |
ea615d51 | 1129 | root, _strerror ("")); |
608de931 | 1130 | } |
93014d67 | 1131 | else |
93014d67 | 1132 | { |
608de931 | 1133 | char *logpath = pathcat (wd, "setup.log"); |
853b9e91 | 1134 | |
608de931 | 1135 | if (logpath) |
93014d67 | 1136 | { |
c1246750 | 1137 | FILE *logfp = fopen (logpath, "w+t"); |
4b40edd0 CF |
1138 | |
1139 | if (logfp == NULL) | |
1140 | { | |
1141 | fprintf (stderr, "Unable to open log file '%s' for writing - %s\n", | |
1142 | logpath, _strerror ("")); | |
1143 | exit (1); | |
1144 | } | |
1145 | ||
608de931 | 1146 | _chdrive (toupper (*root) - 'A' + 1); |
853b9e91 | 1147 | |
608de931 | 1148 | /* Make /bin point to /usr/bin and /lib point to /usr/lib. */ |
6f8e3b45 CF |
1149 | mkmount (wd, root, "bin", "/usr/bin", 1); |
1150 | mkmount (wd, root, "lib", "/usr/lib", 1); | |
853b9e91 | 1151 | |
20904de1 | 1152 | files.count = NFILE_LIST; |
68cdfc92 | 1153 | files.array = calloc (sizeof (char *), NFILE_LIST + NFILE_SLOP); |
20904de1 CF |
1154 | files.index = -1; |
1155 | ||
ea615d51 | 1156 | /* Extract all of the packages that are stored with setup or in |
608de931 | 1157 | subdirectories of its location */ |
20904de1 | 1158 | if (recurse_dirs (wd, logfp)) |
93014d67 | 1159 | { |
608de931 CF |
1160 | char *mount; |
1161 | char buffer[1024]; | |
1162 | ||
1163 | /* Mount the new root directory. */ | |
1164 | mount = pathcat (wd, "mount"); | |
1165 | sprintf (buffer, "%s -f -b \"%s\" /", mount, root); | |
1166 | xfree (mount); | |
ea615d51 | 1167 | if (xsystem (buffer)) |
93014d67 | 1168 | { |
608de931 | 1169 | printf |
93014d67 | 1170 | ("Unable to mount \"%s\" as the root directory: %s", |
608de931 CF |
1171 | root, _strerror ("")); |
1172 | } | |
93014d67 | 1173 | else |
93014d67 | 1174 | { |
68cdfc92 | 1175 | char **a; |
608de931 | 1176 | /* bash expects a /tmp */ |
93014d67 | 1177 | char *tmpdir = pathcat (root, "tmp"); |
853b9e91 | 1178 | |
608de931 | 1179 | if (tmpdir) |
93014d67 | 1180 | { |
68cdfc92 | 1181 | files.array[++files.index] = tmpdir; |
608de931 | 1182 | mkdir (tmpdir); /* Ignore the result, it may |
93014d67 | 1183 | exist. */ |
608de931 | 1184 | } |
853b9e91 | 1185 | |
68cdfc92 CF |
1186 | files.array[++files.index] = pathcat (root, "usr\\local"); |
1187 | files.array[++files.index] = pathcat (root, "usr\\local\\bin"); | |
1188 | files.array[++files.index] = pathcat (root, "usr\\local\\lib"); | |
1189 | mkdirp (files.array[files.index]); | |
1190 | mkdir (files.array[files.index - 1]); | |
1191 | ||
20904de1 | 1192 | if (do_start_menu (root)) |
608de931 | 1193 | retval = 0; /* Everything worked return |
93014d67 | 1194 | successful code */ |
608de931 CF |
1195 | } |
1196 | } | |
853b9e91 | 1197 | |
4b40edd0 | 1198 | fclose (logfp); |
608de931 CF |
1199 | xfree (logpath); |
1200 | } | |
1201 | } | |
853b9e91 | 1202 | |
608de931 | 1203 | xfree (root); |
93014d67 | 1204 | |
608de931 CF |
1205 | chdir (wd); |
1206 | _chdrive (toupper (*wd) - 'A' + 1); | |
1207 | xfree (wd); | |
1208 | } | |
20904de1 | 1209 | |
c73320de | 1210 | printf ("\nInstallation took %.0f seconds.\n", |
20904de1 CF |
1211 | (double) (clock () - start) / CLK_TCK); |
1212 | ||
608de931 | 1213 | return retval; |
93014d67 | 1214 | } |