]> cygwin.com Git - cygwin-apps/setup.git/blob - desktop.cc
2002-07-01 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
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"
36 #include "dialog.h"
37 #include "version.h"
38 #include "mount.h"
39
40 #include "port.h"
41
42 #include "mklink2.h"
43
44 #include "package_db.h"
45 #include "package_meta.h"
46 #include "package_version.h"
47
48 #include "filemanip.h"
49 #include "String++.h"
50 #include "io_stream.h"
51
52 #include "desktop.h"
53 #include "getopt++/BoolOption.h"
54
55 static BoolOption NoShortcutsOption (false, 'n', "no-shortcuts", "Disable creation of desktop and start menu shortcuts");
56
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
67 static const char *etc_profile[] = {
68 "PATH=\"/usr/local/bin:/usr/bin:/bin:$PATH\"",
69 "",
70 "USER=\"`id -un`\"",
71 "",
72 "# Set up USER's home directory",
73 "if [ -z \"$HOME\" ]; then",
74 " HOME=\"/home/$USER\"",
75 "fi",
76 "",
77 "if [ ! -d \"$HOME\" ]; then",
78 " mkdir -p \"$HOME\"",
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 "",
89 "export MAKE_MODE=unix",
90 "export PS1='\\[\\033]0;\\w\\007",
91 "\\033[32m\\]\\u@\\h \\[\\033[33m\\w\\033[0m\\]",
92 "$ '",
93 "",
94 "cd \"$HOME\"",
95 0
96 };
97
98 #define COMMAND9XARGS String("/E:4096 /c")
99 #define COMMAND9XEXE String("\\command.com")
100
101 static String batname;
102 static String iconname;
103
104 static void
105 make_link (String const &linkpath, String const &title, String const &target)
106 {
107 String fname = linkpath + "/" + title + ".lnk";
108
109 if (_access (fname.cstr_oneuse(), 0) == 0)
110 return; /* already exists */
111
112 msg ("make_link %s, %s, %s\n",
113 fname.cstr_oneuse(), title.cstr_oneuse(), target.cstr_oneuse());
114
115 io_stream::mkpath_p (PATH_TO_FILE, String ("file://") + fname);
116
117 String exepath;
118
119 String argbuf;
120 /* If we are running Win9x, build a command line. */
121 if (verinfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
122 {
123 exepath = target;
124 argbuf = " ";
125 // sprintf (argbuf, " ");
126 }
127 else
128 {
129 char windir[MAX_PATH];
130
131 GetWindowsDirectory (windir, sizeof (windir));
132 exepath = String(windir) + COMMAND9XEXE;
133 argbuf = COMMAND9XARGS + " " + target;
134 // sprintf (argbuf, "%s %s", COMMAND9XARGS, target.cstr_oneuse());
135 }
136
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());
142 }
143
144 static void
145 start_menu (String const &title, String const &target)
146 {
147 LPITEMIDLIST id;
148 int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
149 SHGetSpecialFolderLocation (NULL,
150 issystem ? CSIDL_COMMON_PROGRAMS :
151 CSIDL_PROGRAMS, &id);
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)
158 {
159 SHGetSpecialFolderLocation (NULL, CSIDL_PROGRAMS, &id);
160 SHGetPathFromIDList (id, _path);
161 path = String(_path);
162 msg ("Program directory for program link changed to: %s",
163 path.cstr_oneuse());
164 }
165 // end of Win95 addition
166 path += "/Cygwin";
167 make_link (path, title, target);
168 }
169
170 static void
171 desktop_icon (String const &title, String const &target)
172 {
173 char path[_MAX_PATH];
174 LPITEMIDLIST id;
175 int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
176 //SHGetSpecialFolderLocation (NULL, issystem ? CSIDL_DESKTOP : CSIDL_COMMON_DESKTOPDIRECTORY, &id);
177 SHGetSpecialFolderLocation (NULL,
178 issystem ? CSIDL_COMMON_DESKTOPDIRECTORY :
179 CSIDL_DESKTOPDIRECTORY, &id);
180 SHGetPathFromIDList (id, path);
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
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 }
190 // end of Win95 addition
191 make_link (path, title, target);
192 }
193
194 static void
195 make_cygwin_bat ()
196 {
197 batname = backslash (cygpath ("/cygwin.bat"));
198
199 /* if the batch file exists, don't overwrite it */
200 if (_access (batname.cstr_oneuse(), 0) == 0)
201 return;
202
203 FILE *bat = fopen (batname.cstr_oneuse(), "wt");
204 if (!bat)
205 return;
206
207 fprintf (bat, "@echo off\n\n");
208
209 fprintf (bat, "%.2s\n", get_root_dir ().cstr_oneuse());
210 fprintf (bat, "chdir %s\n\n",
211 backslash (get_root_dir () + "/bin").cstr_oneuse());
212
213 fprintf (bat, "bash --login -i\n");
214
215 fclose (bat);
216 }
217
218 static void
219 make_etc_profile ()
220 {
221 String fname = cygpath ("/etc/profile");
222
223 /* if the file exists, don't overwrite it */
224 if (_access (fname.cstr_oneuse(), 0) == 0)
225 return;
226
227 char os;
228 switch (verinfo.dwPlatformId)
229 {
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;
242 }
243 msg ("os is %c", os);
244
245 FILE *p = fopen (fname.cstr_oneuse(), "wb");
246 if (!p)
247 return;
248
249 int i, allow = 1;
250 for (i = 0; etc_profile[i]; i++)
251 {
252 if (etc_profile[i][0] == '@')
253 {
254 allow = 0;
255 msg ("profile: %s", etc_profile[i]);
256 for (const char *cp = etc_profile[i] + 1; *cp; cp++)
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
268 static int
269 uexists (const char *path)
270 {
271 String f = cygpath (path);
272 int a = _access (f.cstr_oneuse(), 0);
273 if (a == 0)
274 return 1;
275 return 0;
276 }
277
278 static void
279 make_passwd_group ()
280 {
281 String fname = cygpath ("/etc/postinstall/passwd-grp.bat");
282 io_stream::mkpath_p (PATH_TO_FILE, String("file://") + fname);
283
284 if ((uexists ("/etc/passwd") || uexists ("/etc/passwd.lnk"))
285 && (uexists ("/etc/group") || uexists ("/etc/group.lnk")))
286 return;
287
288 if (verinfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
289 {
290 packagedb db;
291 packagemeta *pkg = db.packages.getbykey ("cygwin");
292 if (pkg && pkg->installed)
293 {
294 /* mkpasswd and mkgroup are not working on 9x/ME up to 1.1.5-4 */
295 String border_version = canonicalize_version ("1.1.5-4");
296 String inst_version =
297 canonicalize_version (pkg->installed.Canonical_version ());
298 if (inst_version.compare(border_version) <= 0)
299 return;
300 }
301 }
302
303 FILE *p = fopen (fname.cstr_oneuse(), "wt");
304 if (!p)
305 return;
306 if (!(uexists ("/etc/passwd") || uexists ("/etc/passwd.lnk")))
307 fprintf (p, "bin\\mkpasswd -l > etc\\passwd\n");
308 if (!(uexists ("/etc/group") || uexists ("/etc/group.lnk")))
309 fprintf (p, "bin\\mkgroup -l > etc\\group\n");
310 fclose (p);
311 }
312
313 static void
314 save_icon ()
315 {
316 iconname = backslash (cygpath ("/cygwin.ico"));
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
327 FILE *f = fopen (iconname.cstr_oneuse(), "wb");
328 if (f)
329 {
330 fwrite (data, 1, len, f);
331 fclose (f);
332 }
333 }
334
335 static void
336 do_desktop_setup ()
337 {
338 save_icon ();
339
340 make_cygwin_bat ();
341 make_etc_profile ();
342 make_passwd_group ();
343
344 if (root_menu)
345 {
346 start_menu ("Cygwin Bash Shell", batname);
347 }
348
349 if (root_desktop)
350 {
351 desktop_icon ("Cygwin", batname);
352 }
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
372 static int
373 check_desktop (String const title, String const target)
374 {
375 char path[_MAX_PATH];
376 LPITEMIDLIST id;
377 int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
378 SHGetSpecialFolderLocation (NULL,
379 issystem ? CSIDL_COMMON_DESKTOPDIRECTORY :
380 CSIDL_DESKTOPDIRECTORY, &id);
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
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 }
391 // end of Win95 addition
392 String fname = String (path) + "/" + title + ".lnk";
393
394 if (_access (fname.cstr_oneuse(), 0) == 0)
395 return 0; /* already exists */
396
397 fname = String (path) + "/" + title + ".pif"; /* check for a pif as well */
398
399 if (_access (fname.cstr_oneuse(), 0) == 0)
400 return 0; /* already exists */
401
402 return IDC_ROOT_DESKTOP;
403 }
404
405 static int
406 check_startmenu (String const title, String const target)
407 {
408 char path[_MAX_PATH];
409 LPITEMIDLIST id;
410 int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
411 SHGetSpecialFolderLocation (NULL,
412 issystem ? CSIDL_COMMON_PROGRAMS :
413 CSIDL_PROGRAMS, &id);
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
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 }
424 // end of Win95 addition
425 strcat (path, "/Cygwin");
426 String fname = String (path) + "/" + title + ".lnk";
427
428 if (_access (fname.cstr_oneuse(), 0) == 0)
429 return 0; /* already exists */
430
431 fname = String (path) + "/" + title + ".pif"; /* check for a pif as well */
432
433 if (_access (fname.cstr_oneuse(), 0) == 0)
434 return 0; /* already exists */
435
436 return IDC_ROOT_MENU;
437 }
438
439 static void
440 save_dialog (HWND h)
441 {
442 root_desktop = rbget (h, da);
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;
457 }
458 return 0;
459 }
460
461 bool
462 DesktopSetupPage::Create ()
463 {
464 return PropertyPage::Create (NULL, dialog_cmd, IDD_DESKTOP);
465 }
466
467 void
468 DesktopSetupPage::OnInit ()
469 {
470 // FIXME: This CoInitialize() feels like it could be moved to startup in main.cc.
471 CoInitialize (NULL);
472 verinfo.dwOSVersionInfoSize = sizeof (verinfo);
473 GetVersionEx (&verinfo);
474 root_desktop =
475 check_desktop ("Cygwin", backslash (cygpath ("/cygwin.bat")));
476 root_menu =
477 check_startmenu ("Cygwin Bash Shell",
478 backslash (cygpath ("/cygwin.bat")));
479 if (NoShortcutsOption)
480 {
481 root_desktop=false;
482 root_menu=false;
483 OnFinish();
484 }
485 else
486 load_dialog (GetHWND ());
487 }
488
489 long
490 DesktopSetupPage::OnBack ()
491 {
492 HWND h = GetHWND ();
493 save_dialog (h);
494 NEXT (IDD_CHOOSE);
495 return IDD_CHOOSE;
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);
506
507 return true;
508 }
This page took 0.059421 seconds and 5 git commands to generate.