]> cygwin.com Git - cygwin-apps/setup.git/blob - postinstall.cc
Use indents in category view
[cygwin-apps/setup.git] / postinstall.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 run all the post-install scripts
17 in their various forms. */
18
19 #include "dialog.h"
20 #include "find.h"
21 #include "mount.h"
22 #include "script.h"
23 #include "state.h"
24 #include "FindVisitor.h"
25 #include "package_db.h"
26 #include "package_meta.h"
27 #include "resource.h"
28 #include "threebar.h"
29 #include "Exception.h"
30 #include "postinstallresults.h"
31
32 #include <algorithm>
33 #include <sstream>
34
35 extern ThreeBarProgressPage Progress;
36 extern PostInstallResultsPage PostInstallResults;
37
38 // ---------------------------------------------------------------------------
39 //
40 // ---------------------------------------------------------------------------
41
42 class RunFindVisitor : public FindVisitor
43 {
44 public:
45 RunFindVisitor (std::vector<Script> *scripts, const std::string& stratum = "")
46 : _scripts(scripts),
47 stratum(stratum)
48 {}
49 virtual void visitFile(const std::string& basePath,
50 const WIN32_FIND_DATA *theFile)
51 {
52 std::string fn = std::string("/etc/postinstall/") + theFile->cFileName;
53 Script script(fn);
54 if (script.not_p(stratum))
55 _scripts->push_back(Script (fn));
56 }
57 virtual ~ RunFindVisitor () {}
58 protected:
59 RunFindVisitor (RunFindVisitor const &);
60 RunFindVisitor & operator= (RunFindVisitor const &);
61 private:
62 std::vector<Script> *_scripts;
63 const std::string stratum;
64 };
65
66 class PerpetualFindVisitor : public FindVisitor
67 {
68 public:
69 PerpetualFindVisitor (std::vector<Script> *scripts, const std::string& stratum)
70 : _scripts(scripts),
71 stratum(stratum)
72 {}
73 virtual void visitFile(const std::string& basePath,
74 const WIN32_FIND_DATA *theFile)
75 {
76 std::string fn = std::string("/etc/postinstall/") + theFile->cFileName;
77 Script script(fn);
78 if (script.is_p(stratum))
79 _scripts->push_back(Script (fn));
80 }
81 virtual ~ PerpetualFindVisitor () {}
82 protected:
83 PerpetualFindVisitor (PerpetualFindVisitor const &);
84 PerpetualFindVisitor & operator= (PerpetualFindVisitor const &);
85 private:
86 std::vector<Script> *_scripts;
87 const std::string stratum;
88 };
89
90 // ---------------------------------------------------------------------------
91 //
92 // ---------------------------------------------------------------------------
93
94 class RunScript
95 {
96 public:
97 RunScript(const std::string& name, const std::vector<Script> &scripts) : _name(name), _scripts(scripts), _cnt(0)
98 {
99 Progress.SetText2 (name.c_str());
100 Progress.SetBar1 (0, _scripts.size());
101 }
102 virtual ~RunScript()
103 {
104 Progress.SetText3 ("");
105 }
106 int run_one(Script const &aScript)
107 {
108 int retval;
109 Progress.SetText3 (aScript.fullName().c_str());
110 retval = aScript.run();
111 ++_cnt;
112 Progress.SetBar1 (_cnt, _scripts.size());
113 return retval;
114 }
115 void run_all(std::string &s)
116 {
117 bool package_name_recorded = FALSE;
118
119 for (std::vector <Script>::const_iterator j = _scripts.begin();
120 j != _scripts.end();
121 j++)
122 {
123 int retval = run_one(*j);
124
125 if ((retval != 0) && (retval != -ERROR_INVALID_DATA))
126 {
127 if (!package_name_recorded)
128 {
129 s = s + "Package: " + _name + "\r\n";
130 package_name_recorded = TRUE;
131 }
132
133 std::ostringstream fs;
134 fs << "\t" << j->baseName() << " exit code " << retval << "\r\n";
135 s = s + fs.str();
136 }
137 }
138 }
139 private:
140 std::string _name;
141 const std::vector<Script> &_scripts;
142 int _cnt;
143 };
144
145 static std::string
146 do_postinstall_thread (HINSTANCE h, HWND owner)
147 {
148 Progress.SetText1 ("Running...");
149 Progress.SetText2 ("");
150 Progress.SetText3 ("");
151 Progress.SetBar1 (0, 1);
152 Progress.SetBar2 (0, 1);
153
154 packagedb db;
155 std::vector<packagemeta*> packages;
156 PackageDBConnectedIterator i = db.connectedBegin ();
157 while (i != db.connectedEnd ())
158 {
159 packagemeta & pkg = **i;
160 if (pkg.installed)
161 packages.push_back(&pkg);
162 ++i;
163 }
164
165 const std::string postinst = cygpath ("/etc/postinstall");
166 const std::string strata("0_z");
167 std::string s = "";
168 // iterate over all strata
169 for (std::string::const_iterator it = strata.begin(); it != strata.end(); ++it)
170 {
171 const std::string sit(1, *it);
172 // Look for any scripts in /etc/postinstall which should always be run
173 std::vector<Script> perpetual;
174 PerpetualFindVisitor myPerpetualVisitor (&perpetual, sit);
175 Find (postinst).accept (myPerpetualVisitor);
176 // sort the list alphabetically, assumes ASCII names only
177 sort (perpetual.begin(), perpetual.end());
178 // and try to run what we've found
179 {
180 RunScript scriptRunner(sit + "/Perpetual", perpetual);
181 scriptRunner.run_all(s);
182 }
183 // For each package we installed, we noted anything installed into /etc/postinstall.
184 // run those scripts now
185 int numpkg = packages.size() + 1;
186 int k = 0;
187 for (std::vector <packagemeta *>::iterator i = packages.begin (); i != packages.end (); ++i)
188 {
189 packagemeta & pkg = **i;
190
191 std::vector<Script> installed = pkg.scripts();
192 std::vector<Script> run;
193 // extract non-perpetual scripts for the current stratum
194 for (std::vector <Script>::iterator j = installed.begin(); j != installed.end(); j++)
195 {
196 if ((*j).not_p(sit))
197 run.push_back(*j);
198 }
199
200 RunScript scriptRunner(sit + "/" + pkg.name, run);
201 scriptRunner.run_all(s);
202
203 Progress.SetBar2 (++k, numpkg);
204 }
205 // Look for runnable non-perpetual scripts in /etc/postinstall.
206 // This happens when a script from a previous install failed to run.
207 std::vector<Script> scripts;
208 RunFindVisitor myVisitor (&scripts, sit);
209 Find (postinst).accept (myVisitor);
210 // Remove anything which we just tried to run (so we don't try twice)
211 for (std::vector <packagemeta *>::iterator i = packages.begin (); i != packages.end (); ++i)
212 {
213 packagemeta & pkg = **i;
214 for (std::vector<Script>::const_iterator j = pkg.scripts().begin();
215 j != pkg.scripts().end();
216 j++)
217 {
218 std::vector<Script>::iterator p = find(scripts.begin(), scripts.end(), *j);
219 if (p != scripts.end())
220 {
221 scripts.erase(p);
222 }
223 }
224 }
225 // and try to run what's left...
226 {
227 RunScript scriptRunner(sit + "/Unknown package", scripts);
228 scriptRunner.run_all(s);
229 }
230
231 Progress.SetBar2 (numpkg, numpkg);
232
233 }
234 return s;
235 }
236
237 static DWORD WINAPI
238 do_postinstall_reflector (void *p)
239 {
240 HANDLE *context;
241 context = (HANDLE *) p;
242
243 try
244 {
245 std::string s = do_postinstall_thread ((HINSTANCE) context[0], (HWND) context[1]);
246
247 // Tell the postinstall results page the results string
248 PostInstallResults.SetResultsString(s);
249
250 // Tell the progress page that we're done running scripts
251 Progress.PostMessageNow (WM_APP_POSTINSTALL_THREAD_COMPLETE, 0,
252 s.empty() ? IDD_DESKTOP : IDD_POSTINSTALL);
253 }
254 TOPLEVEL_CATCH((HWND) context[1], "postinstall");
255
256 /* Revert primary group to admins group. This allows to create all the
257 state files written by setup as admin group owned. */
258 if (root_scope == IDC_ROOT_SYSTEM)
259 nt_sec.setAdminGroup ();
260
261 ExitThread(0);
262 }
263
264 static HANDLE context[2];
265
266 void
267 do_postinstall (HINSTANCE h, HWND owner)
268 {
269 /* Switch back to original primary group. Otherwise we end up with a
270 broken passwd entry for the current user.
271 FIXME: Unfortunately this has the unfortunate side-effect that *all*
272 files created via postinstall are group owned by the original primary
273 group of the user. Find a way to avoid this at one point. */
274 if (root_scope == IDC_ROOT_SYSTEM)
275 nt_sec.resetPrimaryGroup ();
276
277 context[0] = h;
278 context[1] = owner;
279
280 DWORD threadID;
281 CreateThread (NULL, 0, do_postinstall_reflector, context, 0, &threadID);
282 }
283
This page took 0.050566 seconds and 5 git commands to generate.