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