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