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