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