]> cygwin.com Git - cygwin-apps/setup.git/blob - ini.cc
2004-12-26 Max Bowsher <maxb@ukf.net>
[cygwin-apps/setup.git] / ini.cc
1 /*
2 * Copyright (c) 2000, 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 get and parse the setup.ini file
17 from the mirror site. A few support routines for the bison and
18 flex parsers are provided also. We check to see if this setup.ini
19 is older than the one we used last time, and if so, warn the user. */
20
21 #if 0
22 static const char *cvsid =
23 "\n%%% $Id$\n";
24 #endif
25
26 #include "ini.h"
27
28 #include "csu_util/version_compare.h"
29
30 #include "setup_version.h"
31
32 #include "win32.h"
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <stdarg.h>
37 #include <process.h>
38
39 #include "resource.h"
40 #include "String++.h"
41 #include "state.h"
42 #include "geturl.h"
43 #include "dialog.h"
44 #include "msg.h"
45 #include "log.h"
46 #include "mount.h"
47 #include "site.h"
48 #include "rfc1738.h"
49 #include "find.h"
50 #include "IniParseFindVisitor.h"
51 #include "IniParseFeedback.h"
52 //#include "filemanip.h"
53
54 #include "io_stream.h"
55
56 #include "threebar.h"
57
58 #include "rfc1738.h"
59
60 #include "IniDBBuilderPackage.h"
61 #include "compress.h"
62 #include "Exception.h"
63
64 extern ThreeBarProgressPage Progress;
65
66 unsigned int setup_timestamp = 0;
67 String ini_setup_version;
68
69 extern int yyparse ();
70 /*extern int yydebug;*/
71
72 static char *error_buf = 0;
73 static int error_count = 0;
74
75 static const char *ini_filename;
76
77 class GuiParseFeedback : public IniParseFeedback
78 {
79 public:
80 GuiParseFeedback () : lastpct (0)
81 {
82 Progress.SetText2 ("");
83 Progress.SetText3 ("");
84 Progress.SetText4 ("Progress:");
85 }
86 virtual void progress(unsigned long const pos, unsigned long const max)
87 {
88 if (!max)
89 /* length not known or eof */
90 return;
91 if (lastpct == 100)
92 /* rounding down should mean this only ever fires once */
93 lastpct = 0;
94 if (pos * 100 / max > lastpct)
95 {
96 lastpct = pos * 100 / max;
97 log (LOG_BABBLE, String (lastpct) + "% (" + String (pos) + " of " + String (max) + " bytes of ini file read");
98 }
99 Progress.SetBar1(pos, max);
100 }
101 virtual void iniName (String const &name)
102 {
103 Progress.SetText1 ((String ("Parsing ini file \"") + name + "\"").cstr_oneuse());
104 }
105 virtual void babble(String const &message)const
106 {
107 log (LOG_BABBLE, message);
108 }
109 virtual void warning (String const &message)const
110 {
111 MessageBox (0, message.cstr_oneuse(), "Warning", 0);
112 }
113 virtual void error(String const &message)const
114 {
115 MessageBox (0, message.cstr_oneuse(), "Error parsing", 0);
116 }
117 virtual ~ GuiParseFeedback ()
118 {
119 Progress.SetText4("Package:");
120 }
121 private:
122 unsigned char lastpct;
123 };
124
125 static int
126 do_local_ini (HWND owner)
127 {
128 GuiParseFeedback myFeedback;
129 IniDBBuilderPackage findBuilder(myFeedback);
130 IniParseFindVisitor myVisitor (findBuilder, local_dir, myFeedback);
131 Find (local_dir).accept(myVisitor);
132 setup_timestamp = myVisitor.timeStamp();
133 ini_setup_version = myVisitor.version();
134 return myVisitor.iniCount();
135 }
136
137 static int
138 do_remote_ini (HWND owner)
139 {
140 size_t ini_count = 0;
141 GuiParseFeedback myFeedback;
142 IniDBBuilderPackage aBuilder(myFeedback);
143
144 for (SiteList::const_iterator n = site_list.begin();
145 n != site_list.end(); ++n)
146 {
147 io_stream *compressed_ini_file =
148 get_url_to_membuf (n->url + "/setup.bz2", owner);
149 io_stream *ini_file = 0;
150 if (!compressed_ini_file)
151 ini_file = get_url_to_membuf (n->url + "/setup.ini", owner);
152 else
153 {
154 ini_file = compress::decompress (compressed_ini_file);
155 }
156
157 if (!ini_file)
158 {
159 note (owner, IDS_SETUPINI_MISSING, n->url.cstr_oneuse());
160 continue;
161 }
162
163 if (compressed_ini_file)
164 myFeedback.iniName (n->url + "/setup.bz2");
165 else
166 myFeedback.iniName (n->url + "/setup.ini");
167
168 aBuilder.parse_mirror = n->url;
169 ini_init (ini_file, &aBuilder, myFeedback);
170
171 /*yydebug = 1; */
172
173 if (yyparse () || error_count > 0)
174 MessageBox (0, error_buf,
175 error_count == 1 ? "Parse Error" : "Parse Errors", 0);
176 else
177 {
178 /* save known-good setup.ini locally */
179 String const fp = String ("file://") + local_dir + "/" +
180 rfc1738_escape_part (n->url) +
181 "/setup.ini";
182 io_stream::mkpath_p (PATH_TO_FILE, fp);
183 io_stream *inistream = io_stream::open (fp, "wb");
184 if (inistream)
185 {
186 if (compressed_ini_file)
187 {
188 delete ini_file;
189 compressed_ini_file->seek (0, IO_SEEK_SET);
190 ini_file = compress::decompress (compressed_ini_file);
191 }
192 else
193 ini_file->seek (0, IO_SEEK_SET);
194 if (io_stream::copy (ini_file, inistream))
195 io_stream::remove (fp);
196 delete inistream;
197 }
198 ++ini_count;
199 }
200 if (aBuilder.timestamp > setup_timestamp)
201 {
202 setup_timestamp = aBuilder.timestamp;
203 ini_setup_version = aBuilder.version;
204 }
205 delete ini_file;
206 delete compressed_ini_file;
207 }
208 return ini_count;
209 }
210
211 static bool
212 do_ini_thread (HINSTANCE h, HWND owner)
213 {
214 size_t ini_count = 0;
215 if (source == IDC_SOURCE_CWD)
216 ini_count = do_local_ini (owner);
217 else
218 ini_count = do_remote_ini (owner);
219
220 if (ini_count == 0)
221 return false;
222
223 if (get_root_dir ().cstr_oneuse())
224 {
225 io_stream::mkpath_p (PATH_TO_DIR, "cygfile:///etc/setup");
226
227 unsigned int old_timestamp = 0;
228 io_stream *ots =
229 io_stream::open ("cygfile:///etc/setup/timestamp", "rt");
230 if (ots)
231 {
232 char temp[20];
233 memset (temp, '\0', 20);
234 if (ots->read (temp, 19))
235 sscanf (temp, "%u", &old_timestamp);
236 delete ots;
237 if (old_timestamp && setup_timestamp
238 && (old_timestamp > setup_timestamp))
239 {
240 int yn = yesno (owner, IDS_OLD_SETUPINI);
241 if (yn == IDNO)
242 LogSingleton::GetInstance().exit (1);
243 }
244 }
245 if (setup_timestamp)
246 {
247 io_stream *nts =
248 io_stream::open ("cygfile:///etc/setup/timestamp", "wt");
249 if (nts)
250 {
251 char temp[20];
252 sprintf (temp, "%u", setup_timestamp);
253 nts->write (temp, strlen (temp));
254 delete nts;
255 }
256 }
257 }
258
259 msg (".ini setup_version is %s, our setup_version is %s", ini_setup_version.size() ?
260 ini_setup_version.cstr_oneuse() : "(null)",
261 setup_version);
262 if (ini_setup_version.size())
263 {
264 if (version_compare(setup_version, ini_setup_version) < 0)
265 note (owner, IDS_OLD_SETUP_VERSION, setup_version,
266 ini_setup_version.cstr_oneuse());
267 }
268
269 return true;
270 }
271
272 static DWORD WINAPI
273 do_ini_thread_reflector(void* p)
274 {
275 HANDLE *context;
276 context = (HANDLE*)p;
277
278 try
279 {
280 bool succeeded = do_ini_thread((HINSTANCE)context[0], (HWND)context[1]);
281
282 // Tell the progress page that we're done downloading
283 Progress.PostMessage(WM_APP_SETUP_INI_DOWNLOAD_COMPLETE, 0, succeeded);
284 }
285 TOPLEVEL_CATCH("ini");
286
287 ExitThread(0);
288 }
289
290 static HANDLE context[2];
291
292 void
293 do_ini (HINSTANCE h, HWND owner)
294 {
295 context[0] = h;
296 context[1] = owner;
297
298 DWORD threadID;
299 CreateThread (NULL, 0, do_ini_thread_reflector, context, 0, &threadID);
300 }
301
302
303 extern int yylineno;
304 extern int yybol ();
305
306 extern int
307 yyerror (String const &s)
308 {
309 char buf[MAX_PATH + 1000];
310 int len;
311 sprintf (buf, "%s line %d: ", ini_filename, yylineno - yybol ());
312 sprintf (buf + strlen (buf), s.cstr_oneuse());
313 OutputDebugString (buf);
314 if (error_buf)
315 {
316 strcat (error_buf, "\n");
317 len = strlen (error_buf) + strlen (buf) + 5;
318 error_buf = (char *) realloc (error_buf, len);
319 strcat (error_buf, buf);
320 }
321 else
322 {
323 len = strlen (buf) + 5;
324 error_buf = (char *) malloc (len);
325 strcpy (error_buf, buf);
326 }
327 error_count++;
328 /* TODO: is return 0 correct? */
329 return 0;
330 }
331
332 extern "C" int fprintf (FILE * f, const char *s, ...);
333
334 static char stderrbuf[1000];
335
336 int
337 fprintf (FILE * f, const char *fmt, ...)
338 {
339 char buf[1000];
340 int rv;
341 va_list args;
342 va_start (args, fmt);
343 if (f == stderr)
344 {
345 rv = vsnprintf (buf, 1000, fmt, args);
346 /* todo check here for overflows too */
347 strcat (stderrbuf, buf);
348 if (char *nl = strchr (stderrbuf, '\n'))
349 {
350 *nl = 0;
351 /*OutputDebugString (stderrbuf); */
352 MessageBox (0, buf, "Cygwin Setup", 0);
353 stderrbuf[0] = 0;
354 }
355
356 }
357 else
358 {
359 rv = vfprintf (f, fmt, args);
360 }
361 return rv;
362 }
This page took 0.051299 seconds and 5 git commands to generate.