]>
Commit | Line | Data |
---|---|---|
904d24fe | 1 | /* |
31324d15 | 2 | * Copyright (c) 2000, 2001 Red Hat, Inc. |
904d24fe DD |
3 | * |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * A copy of the GNU General Public License can be found at | |
10 | * http://www.gnu.org/ | |
11 | * | |
12 | * Written by DJ Delorie <dj@cygnus.com> | |
13 | * | |
14 | */ | |
15 | ||
16 | /* The purpose of this file is to manage all the desktop setup, such | |
17 | as start menu, batch files, desktop icons, and shortcuts. Note | |
18 | that unlike other do_* functions, this one is called directly from | |
19 | install.cc */ | |
20 | ||
b24c88b3 RC |
21 | #if 0 |
22 | static const char *cvsid = | |
23 | "\n%%% $Id$\n"; | |
24 | #endif | |
8507f105 | 25 | |
904d24fe | 26 | #include "win32.h" |
ad09bcd9 | 27 | #include <shlobj.h> |
904d24fe DD |
28 | |
29 | #include <stdio.h> | |
30 | #include <stdlib.h> | |
31 | #include <unistd.h> | |
32 | ||
33 | #include "resource.h" | |
ef2007fd | 34 | #include "ini.h" |
904d24fe DD |
35 | #include "msg.h" |
36 | #include "state.h" | |
904d24fe | 37 | #include "dialog.h" |
ef2007fd | 38 | #include "version.h" |
a351e48c | 39 | #include "mount.h" |
904d24fe DD |
40 | |
41 | #include "port.h" | |
42 | ||
b24c88b3 | 43 | #include "mklink2.h" |
904d24fe | 44 | |
bb849dbd RC |
45 | #include "package_db.h" |
46 | #include "package_meta.h" | |
47 | #include "package_version.h" | |
48 | ||
3c054baf RC |
49 | #include "filemanip.h" |
50 | #include "String++.h" | |
51 | #include "io_stream.h" | |
52 | ||
ab57ceaa RC |
53 | #include "desktop.h" |
54 | ||
3c054baf | 55 | |
3a8e3956 DD |
56 | static OSVERSIONINFO verinfo; |
57 | ||
58 | /* Lines starting with '@' are conditionals - include 'N' for NT, | |
59 | '5' for Win95, '8' for Win98, '*' for all, like this: | |
60 | echo foo | |
61 | @N8 | |
62 | echo NT or 98 | |
63 | @* | |
64 | */ | |
65 | ||
b24c88b3 | 66 | static const char *etc_profile[] = { |
a6100861 | 67 | "PATH=\"/usr/local/bin:/usr/bin:/bin:$PATH\"", |
e0c3d906 | 68 | "", |
40aef45e | 69 | "USER=\"`id -un`\"", |
e0c3d906 DD |
70 | "", |
71 | "# Set up USER's home directory", | |
72 | "if [ -z \"$HOME\" ]; then", | |
40aef45e | 73 | " HOME=\"/home/$USER\"", |
e0c3d906 DD |
74 | "fi", |
75 | "", | |
40aef45e DD |
76 | "if [ ! -d \"$HOME\" ]; then", |
77 | " mkdir -p \"$HOME\"", | |
e0c3d906 DD |
78 | "fi", |
79 | "", | |
80 | "export HOME USER", | |
81 | "", | |
82 | "for i in /etc/profile.d/*.sh ; do", | |
83 | " if [ -f $i ]; then", | |
84 | " . $i", | |
85 | " fi", | |
86 | "done", | |
87 | "", | |
bf1d5889 | 88 | "export MAKE_MODE=unix", |
dd3f7f9b DD |
89 | "export PS1='\\[\\033]0;\\w\\007", |
90 | "\\033[32m\\]\\u@\\h \\[\\033[33m\\w\\033[0m\\]", | |
e0c3d906 DD |
91 | "$ '", |
92 | "", | |
40aef45e | 93 | "cd \"$HOME\"", |
e0c3d906 DD |
94 | 0 |
95 | }; | |
96 | ||
3c054baf RC |
97 | #define COMMAND9XARGS String("/E:4096 /c") |
98 | #define COMMAND9XEXE String("\\command.com") | |
904d24fe | 99 | |
3c054baf RC |
100 | static String batname; |
101 | static String iconname; | |
904d24fe | 102 | |
904d24fe | 103 | static void |
3c054baf | 104 | make_link (String const &linkpath, String const &title, String const &target) |
904d24fe | 105 | { |
3c054baf | 106 | String fname = linkpath + "/" + title + ".lnk"; |
904d24fe | 107 | |
3c054baf | 108 | if (_access (fname.cstr_oneuse(), 0) == 0) |
b24c88b3 | 109 | return; /* already exists */ |
904d24fe | 110 | |
3c054baf | 111 | msg ("make_link %s, %s, %s\n", fname.cstr_oneuse(), title.cstr_oneuse(), target.cstr_oneuse()); |
904d24fe | 112 | |
3c054baf | 113 | io_stream::mkpath_p (PATH_TO_FILE, fname); |
904d24fe | 114 | |
3c054baf | 115 | String exepath; |
904d24fe | 116 | |
3c054baf | 117 | String argbuf; |
904d24fe | 118 | /* If we are running Win9x, build a command line. */ |
904d24fe DD |
119 | if (verinfo.dwPlatformId == VER_PLATFORM_WIN32_NT) |
120 | { | |
3c054baf RC |
121 | exepath = target; |
122 | argbuf = " "; | |
123 | // sprintf (argbuf, " "); | |
904d24fe DD |
124 | } |
125 | else | |
126 | { | |
904d24fe DD |
127 | char windir[MAX_PATH]; |
128 | ||
129 | GetWindowsDirectory (windir, sizeof (windir)); | |
3c054baf RC |
130 | exepath = String(windir) + COMMAND9XEXE; |
131 | argbuf = COMMAND9XARGS + " " + target; | |
132 | // sprintf (argbuf, "%s %s", COMMAND9XARGS, target.cstr_oneuse()); | |
904d24fe DD |
133 | } |
134 | ||
3c054baf RC |
135 | msg ("make_link_2 (%s, %s, %s, %s)", exepath.cstr_oneuse(), argbuf.cstr_oneuse(), iconname.cstr_oneuse(), fname.cstr_oneuse()); |
136 | make_link_2 (exepath.cstr_oneuse(), argbuf.cstr_oneuse(), iconname.cstr_oneuse(), fname.cstr_oneuse()); | |
904d24fe DD |
137 | } |
138 | ||
139 | static void | |
3c054baf | 140 | start_menu (String const &title, String const &target) |
904d24fe | 141 | { |
904d24fe | 142 | LPITEMIDLIST id; |
24e259bb | 143 | int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0; |
b24c88b3 RC |
144 | SHGetSpecialFolderLocation (NULL, |
145 | issystem ? CSIDL_COMMON_PROGRAMS : | |
146 | CSIDL_PROGRAMS, &id); | |
3c054baf RC |
147 | char _path[_MAX_PATH]; |
148 | SHGetPathFromIDList (id, _path); | |
149 | String path(_path); | |
150 | // Win95 does not use common programs unless multiple users for Win95 is enabled | |
151 | msg ("Program directory for program link: %s", path.cstr_oneuse()); | |
152 | if (path.size() == 0) | |
b24c88b3 RC |
153 | { |
154 | SHGetSpecialFolderLocation (NULL, CSIDL_PROGRAMS, &id); | |
3c054baf RC |
155 | SHGetPathFromIDList (id, _path); |
156 | path = String(_path); | |
157 | msg ("Program directory for program link changed to: %s", path.cstr_oneuse()); | |
b24c88b3 | 158 | } |
50225eae | 159 | // end of Win95 addition |
3c054baf | 160 | path += "/Cygwin"; |
904d24fe DD |
161 | make_link (path, title, target); |
162 | } | |
163 | ||
164 | static void | |
3c054baf | 165 | desktop_icon (String const &title, String const &target) |
904d24fe DD |
166 | { |
167 | char path[_MAX_PATH]; | |
168 | LPITEMIDLIST id; | |
24e259bb | 169 | int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0; |
50225eae | 170 | //SHGetSpecialFolderLocation (NULL, issystem ? CSIDL_DESKTOP : CSIDL_COMMON_DESKTOPDIRECTORY, &id); |
b24c88b3 RC |
171 | SHGetSpecialFolderLocation (NULL, |
172 | issystem ? CSIDL_COMMON_DESKTOPDIRECTORY : | |
173 | CSIDL_DESKTOPDIRECTORY, &id); | |
904d24fe | 174 | SHGetPathFromIDList (id, path); |
50225eae DD |
175 | // following lines added because it appears Win95 does not use common programs |
176 | // unless it comes into play when multiple users for Win95 is enabled | |
b24c88b3 RC |
177 | msg ("Desktop directory for desktop link: %s", path); |
178 | if (strlen (path) == 0) | |
179 | { | |
180 | SHGetSpecialFolderLocation (NULL, CSIDL_DESKTOPDIRECTORY, &id); | |
181 | SHGetPathFromIDList (id, path); | |
182 | msg ("Desktop directory for deskop link changed to: %s", path); | |
183 | } | |
50225eae | 184 | // end of Win95 addition |
904d24fe DD |
185 | make_link (path, title, target); |
186 | } | |
187 | ||
188 | static void | |
189 | make_cygwin_bat () | |
190 | { | |
a351e48c | 191 | batname = backslash (cygpath ("/cygwin.bat", 0)); |
904d24fe DD |
192 | |
193 | /* if the batch file exists, don't overwrite it */ | |
3c054baf | 194 | if (_access (batname.cstr_oneuse(), 0) == 0) |
904d24fe DD |
195 | return; |
196 | ||
3c054baf | 197 | FILE *bat = fopen (batname.cstr_oneuse(), "wt"); |
904d24fe DD |
198 | if (!bat) |
199 | return; | |
200 | ||
201 | fprintf (bat, "@echo off\n\n"); | |
202 | ||
3c054baf | 203 | fprintf (bat, "%.2s\n", get_root_dir ().cstr_oneuse()); |
b24c88b3 | 204 | fprintf (bat, "chdir %s\n\n", |
3c054baf | 205 | backslash (get_root_dir () + "/bin").cstr_oneuse()); |
904d24fe DD |
206 | |
207 | fprintf (bat, "bash --login -i\n"); | |
208 | ||
209 | fclose (bat); | |
904d24fe DD |
210 | } |
211 | ||
e0c3d906 DD |
212 | static void |
213 | make_etc_profile () | |
214 | { | |
3c054baf | 215 | String fname = cygpath ("/etc/profile", 0); |
e0c3d906 DD |
216 | |
217 | /* if the file exists, don't overwrite it */ | |
3c054baf | 218 | if (_access (fname.cstr_oneuse(), 0) == 0) |
e0c3d906 DD |
219 | return; |
220 | ||
3a8e3956 DD |
221 | char os; |
222 | switch (verinfo.dwPlatformId) | |
223 | { | |
b24c88b3 RC |
224 | case VER_PLATFORM_WIN32_NT: |
225 | os = 'N'; | |
226 | break; | |
227 | case VER_PLATFORM_WIN32_WINDOWS: | |
228 | if (verinfo.dwMinorVersion == 0) | |
229 | os = '5'; | |
230 | else | |
231 | os = '8'; | |
232 | break; | |
233 | default: | |
234 | os = '?'; | |
235 | break; | |
3a8e3956 DD |
236 | } |
237 | msg ("os is %c", os); | |
238 | ||
3c054baf | 239 | FILE *p = fopen (fname.cstr_oneuse(), "wb"); |
e0c3d906 DD |
240 | if (!p) |
241 | return; | |
242 | ||
b24c88b3 RC |
243 | int i, allow = 1; |
244 | for (i = 0; etc_profile[i]; i++) | |
3a8e3956 DD |
245 | { |
246 | if (etc_profile[i][0] == '@') | |
247 | { | |
248 | allow = 0; | |
249 | msg ("profile: %s", etc_profile[i]); | |
b24c88b3 | 250 | for (const char *cp = etc_profile[i] + 1; *cp; cp++) |
3a8e3956 DD |
251 | if (*cp == os || *cp == '*') |
252 | allow = 1; | |
253 | msg ("allow is %d\n", allow); | |
254 | } | |
255 | else if (allow) | |
256 | fprintf (p, "%s\n", etc_profile[i]); | |
257 | } | |
258 | ||
259 | fclose (p); | |
260 | } | |
261 | ||
f57c332f | 262 | static int |
b24c88b3 | 263 | uexists (const char *path) |
f57c332f | 264 | { |
3c054baf RC |
265 | String f = cygpath (path, 0); |
266 | int a = _access (f.cstr_oneuse(), 0); | |
f57c332f DD |
267 | if (a == 0) |
268 | return 1; | |
269 | return 0; | |
270 | } | |
271 | ||
3a8e3956 | 272 | static void |
f57c332f | 273 | make_passwd_group () |
3a8e3956 | 274 | { |
3c054baf RC |
275 | String fname = cygpath ("/etc/postinstall/passwd-grp.bat", 0); |
276 | io_stream::mkpath_p (PATH_TO_FILE, fname); | |
31324d15 | 277 | |
3c054baf | 278 | FILE *p = fopen (fname.cstr_oneuse(), "wt"); |
31324d15 CF |
279 | if (!p) |
280 | return; | |
3a8e3956 | 281 | if (verinfo.dwPlatformId != VER_PLATFORM_WIN32_NT) |
ef2007fd | 282 | { |
bb849dbd | 283 | packagedb db; |
cbfc4215 | 284 | packagemeta *pkg = db.packages.getbykey ("cygwin"); |
bb849dbd | 285 | if (pkg && pkg->installed) |
ef2007fd | 286 | { |
c46a33a9 | 287 | /* mkpasswd and mkgroup are not working on 9x/ME up to 1.1.5-4 */ |
3c054baf RC |
288 | String border_version = canonicalize_version ("1.1.5-4"); |
289 | String inst_version = | |
bb849dbd | 290 | canonicalize_version (pkg->installed->Canonical_version ()); |
3c054baf | 291 | if (inst_version.compare(border_version) <= 0) |
31324d15 | 292 | goto out; |
ef2007fd CV |
293 | } |
294 | } | |
3a8e3956 | 295 | |
f57c332f | 296 | if (uexists ("/etc/passwd") && uexists ("/etc/group")) |
31324d15 | 297 | goto out; |
3a8e3956 | 298 | |
f57c332f DD |
299 | if (!uexists ("/etc/passwd")) |
300 | fprintf (p, "bin\\mkpasswd -l > etc\\passwd\n"); | |
301 | if (!uexists ("/etc/group")) | |
302 | fprintf (p, "bin\\mkgroup -l > etc\\group\n"); | |
e0c3d906 | 303 | |
b24c88b3 | 304 | out: |
e0c3d906 DD |
305 | fclose (p); |
306 | } | |
307 | ||
904d24fe DD |
308 | static void |
309 | save_icon () | |
310 | { | |
a351e48c | 311 | iconname = backslash (cygpath ("/cygwin.ico", 0)); |
904d24fe DD |
312 | |
313 | HRSRC rsrc = FindResource (NULL, "CYGWIN.ICON", "FILE"); | |
314 | if (rsrc == NULL) | |
315 | { | |
316 | fatal ("FindResource failed"); | |
317 | } | |
318 | HGLOBAL res = LoadResource (NULL, rsrc); | |
319 | char *data = (char *) LockResource (res); | |
320 | int len = SizeofResource (NULL, rsrc); | |
321 | ||
3c054baf | 322 | FILE *f = fopen (iconname.cstr_oneuse(), "wb"); |
904d24fe DD |
323 | if (f) |
324 | { | |
325 | fwrite (data, 1, len, f); | |
326 | fclose (f); | |
327 | } | |
328 | } | |
329 | ||
50225eae | 330 | static void |
b24c88b3 | 331 | do_desktop_setup () |
50225eae DD |
332 | { |
333 | save_icon (); | |
334 | ||
335 | make_cygwin_bat (); | |
336 | make_etc_profile (); | |
337 | make_passwd_group (); | |
338 | ||
b24c88b3 RC |
339 | if (root_menu) |
340 | { | |
341 | start_menu ("Cygwin Bash Shell", batname); | |
342 | } | |
50225eae | 343 | |
b24c88b3 RC |
344 | if (root_desktop) |
345 | { | |
346 | desktop_icon ("Cygwin", batname); | |
347 | } | |
50225eae DD |
348 | } |
349 | ||
350 | static int da[] = { IDC_ROOT_DESKTOP, 0 }; | |
351 | static int ma[] = { IDC_ROOT_MENU, 0 }; | |
352 | ||
353 | static void | |
354 | check_if_enable_next (HWND h) | |
355 | { | |
356 | EnableWindow (GetDlgItem (h, IDOK), 1); | |
357 | } | |
358 | ||
359 | static void | |
360 | load_dialog (HWND h) | |
361 | { | |
362 | rbset (h, da, root_desktop); | |
363 | rbset (h, ma, root_menu); | |
364 | check_if_enable_next (h); | |
365 | } | |
366 | ||
b24c88b3 | 367 | static int |
3c054baf | 368 | check_desktop (String const title, String const target) |
50225eae DD |
369 | { |
370 | char path[_MAX_PATH]; | |
371 | LPITEMIDLIST id; | |
372 | int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0; | |
b24c88b3 RC |
373 | SHGetSpecialFolderLocation (NULL, |
374 | issystem ? CSIDL_COMMON_DESKTOPDIRECTORY : | |
375 | CSIDL_DESKTOPDIRECTORY, &id); | |
50225eae DD |
376 | SHGetPathFromIDList (id, path); |
377 | // following lines added because it appears Win95 does not use common programs | |
378 | // unless it comes into play when multiple users for Win95 is enabled | |
b24c88b3 RC |
379 | msg ("Desktop directory for desktop link: %s", path); |
380 | if (strlen (path) == 0) | |
381 | { | |
382 | SHGetSpecialFolderLocation (NULL, CSIDL_DESKTOPDIRECTORY, &id); | |
383 | SHGetPathFromIDList (id, path); | |
384 | msg ("Desktop directory for deskop link changed to: %s", path); | |
385 | } | |
50225eae | 386 | // end of Win95 addition |
3c054baf | 387 | String fname = String::concat (path, "/", title.cstr_oneuse(), ".lnk", 0); |
50225eae | 388 | |
3c054baf | 389 | if (_access (fname.cstr_oneuse(), 0) == 0) |
b24c88b3 | 390 | return 0; /* already exists */ |
42bf5b92 | 391 | |
3c054baf | 392 | fname = String::concat (path, "/", title.cstr_oneuse(), ".pif", 0); /* check for a pif as well */ |
42bf5b92 | 393 | |
3c054baf | 394 | if (_access (fname.cstr_oneuse(), 0) == 0) |
b24c88b3 | 395 | return 0; /* already exists */ |
50225eae DD |
396 | |
397 | return IDC_ROOT_DESKTOP; | |
398 | } | |
399 | ||
b24c88b3 | 400 | static int |
3c054baf | 401 | check_startmenu (String const title, String const target) |
50225eae DD |
402 | { |
403 | char path[_MAX_PATH]; | |
404 | LPITEMIDLIST id; | |
405 | int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0; | |
b24c88b3 RC |
406 | SHGetSpecialFolderLocation (NULL, |
407 | issystem ? CSIDL_COMMON_PROGRAMS : | |
408 | CSIDL_PROGRAMS, &id); | |
50225eae DD |
409 | SHGetPathFromIDList (id, path); |
410 | // following lines added because it appears Win95 does not use common programs | |
411 | // unless it comes into play when multiple users for Win95 is enabled | |
b24c88b3 RC |
412 | msg ("Program directory for program link: %s", path); |
413 | if (strlen (path) == 0) | |
414 | { | |
415 | SHGetSpecialFolderLocation (NULL, CSIDL_PROGRAMS, &id); | |
416 | SHGetPathFromIDList (id, path); | |
417 | msg ("Program directory for program link changed to: %s", path); | |
418 | } | |
50225eae | 419 | // end of Win95 addition |
398dd7b2 | 420 | strcat (path, "/Cygwin"); |
3c054baf | 421 | String fname = String::concat (path, "/", title.cstr_oneuse(), ".lnk", 0); |
50225eae | 422 | |
3c054baf | 423 | if (_access (fname.cstr_oneuse(), 0) == 0) |
b24c88b3 | 424 | return 0; /* already exists */ |
42bf5b92 | 425 | |
3c054baf | 426 | fname = String::concat (path, "/", title.cstr_oneuse(), ".pif", 0); /* check for a pif as well */ |
42bf5b92 | 427 | |
3c054baf | 428 | if (_access (fname.cstr_oneuse(), 0) == 0) |
b24c88b3 | 429 | return 0; /* already exists */ |
42bf5b92 | 430 | |
50225eae DD |
431 | return IDC_ROOT_MENU; |
432 | } | |
433 | ||
434 | static void | |
435 | save_dialog (HWND h) | |
436 | { | |
b24c88b3 | 437 | root_desktop = rbget (h, da); |
50225eae DD |
438 | root_menu = rbget (h, ma); |
439 | } | |
440 | ||
441 | static BOOL | |
442 | dialog_cmd (HWND h, int id, HWND hwndctl, UINT code) | |
443 | { | |
444 | switch (id) | |
445 | { | |
446 | ||
447 | case IDC_ROOT_DESKTOP: | |
448 | case IDC_ROOT_MENU: | |
449 | save_dialog (h); | |
450 | check_if_enable_next (h); | |
451 | break; | |
50225eae | 452 | } |
b24c88b3 | 453 | return 0; |
50225eae DD |
454 | } |
455 | ||
ab57ceaa RC |
456 | bool |
457 | DesktopSetupPage::Create () | |
50225eae | 458 | { |
ab57ceaa | 459 | return PropertyPage::Create (NULL, dialog_cmd, IDD_DESKTOP); |
50225eae DD |
460 | } |
461 | ||
904d24fe | 462 | void |
ab57ceaa | 463 | DesktopSetupPage::OnInit () |
904d24fe | 464 | { |
ab57ceaa | 465 | // FIXME: This CoInitialize() feels like it could be moved to startup in main.cc. |
904d24fe | 466 | CoInitialize (NULL); |
3a8e3956 DD |
467 | verinfo.dwOSVersionInfoSize = sizeof (verinfo); |
468 | GetVersionEx (&verinfo); | |
b24c88b3 RC |
469 | root_desktop = |
470 | check_desktop ("Cygwin", backslash (cygpath ("/cygwin.bat", 0))); | |
471 | root_menu = | |
472 | check_startmenu ("Cygwin Bash Shell", | |
473 | backslash (cygpath ("/cygwin.bat", 0))); | |
ab57ceaa RC |
474 | load_dialog (GetHWND ()); |
475 | } | |
42bf5b92 | 476 | |
ab57ceaa RC |
477 | long |
478 | DesktopSetupPage::OnBack () | |
479 | { | |
480 | HWND h = GetHWND (); | |
481 | save_dialog (h); | |
482 | NEXT (IDD_CHOOSE); | |
483 | return IDD_CHOOSER; | |
484 | } | |
485 | ||
486 | bool | |
487 | DesktopSetupPage::OnFinish () | |
488 | { | |
489 | HWND h = GetHWND (); | |
490 | save_dialog (h); | |
491 | do_desktop_setup (); | |
492 | NEXT (IDD_S_POSTINSTALL); | |
493 | do_postinstall (GetInstance (), h); | |
904d24fe | 494 | |
ab57ceaa | 495 | return true; |
904d24fe | 496 | } |