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