Translated using Weblate (Chinese (Simplified))
[cygwin-setup.git] / postinstall.cc
blob32bc401bde3d689b7792ea7b508b9d0786ddee58
1 /*
2 * Copyright (c) 2000, 2001 Red Hat, Inc.
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.
9 * A copy of the GNU General Public License can be found at
10 * http://www.gnu.org/
12 * Written by DJ Delorie <dj@cygnus.com>
16 /* The purpose of this file is to run all the post-install scripts
17 in their various forms. */
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"
32 #include <algorithm>
33 #include <sstream>
35 extern ThreeBarProgressPage Progress;
36 extern PostInstallResultsPage PostInstallResults;
38 // ---------------------------------------------------------------------------
40 // ---------------------------------------------------------------------------
42 class RunFindVisitor : public FindVisitor
44 public:
45 RunFindVisitor (std::vector<Script> *scripts, const std::string& stratum = "")
46 : _scripts(scripts),
47 stratum(stratum)
49 virtual void visitFile(const std::string& basePath,
50 const WIN32_FIND_DATA *theFile)
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));
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;
66 class PerpetualFindVisitor : public FindVisitor
68 public:
69 PerpetualFindVisitor (std::vector<Script> *scripts, const std::string& stratum)
70 : _scripts(scripts),
71 stratum(stratum)
73 virtual void visitFile(const std::string& basePath,
74 const WIN32_FIND_DATA *theFile)
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));
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;
90 // ---------------------------------------------------------------------------
92 // ---------------------------------------------------------------------------
94 class RunScript
96 public:
97 RunScript(const std::string& name, const std::vector<Script> &scripts) : _name(name), _scripts(scripts), _cnt(0)
99 Progress.SetText2 (name.c_str());
100 Progress.SetBar1 (0, _scripts.size());
102 virtual ~RunScript()
104 Progress.SetText3 ("");
106 int run_one(Script const &aScript)
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;
115 void run_all(std::string &s)
117 bool package_name_recorded = FALSE;
119 for (std::vector <Script>::const_iterator j = _scripts.begin();
120 j != _scripts.end();
121 j++)
123 int retval = run_one(*j);
125 if ((retval != 0) && (retval != -ERROR_INVALID_DATA))
127 if (!package_name_recorded)
129 s = s + "Package: " + _name + "\r\n";
130 package_name_recorded = TRUE;
133 std::ostringstream fs;
134 fs << "\t" << j->baseName() << " exit code " << retval << "\r\n";
135 s = s + fs.str();
139 private:
140 std::string _name;
141 const std::vector<Script> &_scripts;
142 int _cnt;
145 static std::string
146 do_postinstall_thread (HINSTANCE h, HWND owner)
148 Progress.SetText1 (IDS_PROGRESS_POSTINSTALL);
149 Progress.SetText2 ("");
150 Progress.SetText3 ("");
151 Progress.SetBar1 (0, 1);
152 Progress.SetBar2 (0, 1);
154 packagedb db;
155 std::vector<packagemeta*> packages;
156 PackageDBConnectedIterator i = db.connectedBegin ();
157 while (i != db.connectedEnd ())
159 packagemeta & pkg = **i;
160 if (pkg.installed)
161 packages.push_back(&pkg);
162 ++i;
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)
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
180 RunScript scriptRunner(sit + "/Perpetual", perpetual);
181 scriptRunner.run_all(s);
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)
189 packagemeta & pkg = **i;
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++)
196 if ((*j).not_p(sit))
197 run.push_back(*j);
200 RunScript scriptRunner(sit + "/" + pkg.name, run);
201 scriptRunner.run_all(s);
203 Progress.SetBar2 (++k, numpkg);
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)
213 packagemeta & pkg = **i;
214 for (std::vector<Script>::const_iterator j = pkg.scripts().begin();
215 j != pkg.scripts().end();
216 j++)
218 std::vector<Script>::iterator p = find(scripts.begin(), scripts.end(), *j);
219 if (p != scripts.end())
221 scripts.erase(p);
225 // and try to run what's left...
227 RunScript scriptRunner(sit + "/Unknown package", scripts);
228 scriptRunner.run_all(s);
231 Progress.SetBar2 (numpkg, numpkg);
234 return s;
237 static DWORD WINAPI
238 do_postinstall_reflector (void *p)
240 HANDLE *context;
241 context = (HANDLE *) p;
243 SetThreadUILanguage(langid);
247 std::string s = do_postinstall_thread ((HINSTANCE) context[0], (HWND) context[1]);
249 // Tell the postinstall results page the results string
250 PostInstallResults.SetResultsString(s);
252 // Tell the progress page that we're done running scripts
253 Progress.PostMessageNow (WM_APP_POSTINSTALL_THREAD_COMPLETE, 0,
254 s.empty() ? IDD_DESKTOP : IDD_POSTINSTALL);
256 TOPLEVEL_CATCH((HWND) context[1], "postinstall");
258 ExitThread(0);
261 static HANDLE context[2];
263 void
264 do_postinstall (HINSTANCE h, HWND owner)
266 context[0] = h;
267 context[1] = owner;
269 DWORD threadID;
270 CreateThread (NULL, 0, do_postinstall_reflector, context, 0, &threadID);