flex parsers are provided also. We check to see if this setup.ini
is older than the one we used last time, and if so, warn the user. */
+#if 0
+static const char *cvsid =
+ "\n%%% $Id$\n";
+#endif
+
#include "win32.h"
#include <stdio.h>
+#include <stdlib.h>
#include <stdarg.h>
+#include <process.h>
#include "ini.h"
#include "resource.h"
-#include "concat.h"
+#include "String++.h"
#include "state.h"
#include "geturl.h"
#include "dialog.h"
#include "msg.h"
-#include "mkdir.h"
+#include "log.h"
+#include "version.h"
+#include "mount.h"
+#include "site.h"
+#include "rfc1738.h"
+#include "find.h"
+#include "IniParseFindVisitor.h"
+#include "IniParseFeedback.h"
+//#include "filemanip.h"
+
+#include "io_stream.h"
+
+#include "threebar.h"
+
+#include "rfc1738.h"
+
+#include "IniDBBuilderPackage.h"
+#include "compress.h"
+
+extern ThreeBarProgressPage Progress;
unsigned int setup_timestamp = 0;
+String setup_version;
-extern "C" int yyparse ();
-/* extern int yydebug; */
+extern int yyparse ();
+/*extern int yydebug;*/
-void
-do_ini (HINSTANCE h)
+static char *error_buf = 0;
+static int error_count = 0;
+
+static const char *ini_filename;
+
+class GuiParseFeedback : public IniParseFeedback
+{
+public:
+ virtual void babble(String const &message)const
+ {
+ log (LOG_BABBLE, message);
+ }
+ virtual void warning (String const &message)const
+ {
+ MessageBox (0, message.cstr_oneuse(), "Warning", 0);
+ }
+ virtual void error(String const &message)const
+ {
+ MessageBox (0, message.cstr_oneuse(), "Error parsing", 0);
+ }
+ virtual ~ GuiParseFeedback ()
+ {
+ }
+};
+
+static int
+do_local_ini (HWND owner)
{
- char *ini_file = get_url_to_string (concat (MIRROR_SITE, "/setup.ini", 0));
+ GuiParseFeedback myFeedback;
+ IniDBBuilderPackage findBuilder(myFeedback);
+ IniParseFindVisitor myVisitor (findBuilder, local_dir, myFeedback);
+ Find (local_dir).accept(myVisitor);
+ setup_timestamp = myVisitor.timeStamp();
+ setup_version = myVisitor.version();
+ return myVisitor.iniCount();
+}
- if (!ini_file)
- fatal (IDS_SETUPINI_MISSING, MIRROR_SITE);
+static int
+do_remote_ini (HWND owner)
+{
+ size_t ini_count = 0;
+ GuiParseFeedback myFeedback;
+ IniDBBuilderPackage aBuilder(myFeedback);
+
+ for (size_t n = 1; n <= site_list.number (); n++)
+ {
+ io_stream *compressed_ini_file =
+ get_url_to_membuf (site_list[n]->url + "/setup.bz2", owner);
+ io_stream *ini_file = 0;
+ if (!compressed_ini_file)
+ ini_file = get_url_to_membuf (site_list[n]->url + "/setup.ini", owner);
+ else
+ {
+ ini_file = compress::decompress (compressed_ini_file);
+ }
- ini_init (ini_file);
+ if (!ini_file)
+ {
+ note (owner, IDS_SETUPINI_MISSING, site_list[n]->url.cstr_oneuse());
+ continue;
+ }
- setup_timestamp = 0;
- /* yydebug = 0;*/
- yyparse();
+ aBuilder.parse_mirror = site_list[n]->url;
+ ini_init (ini_file, &aBuilder);
- mkdir_p (1, concat (root_dir, "/etc/setup", 0));
+ /*yydebug = 1; */
- unsigned int old_timestamp = 0;
- FILE *ots = fopen (concat (root_dir, "/etc/setup/timestamp", 0), "rt");
- if (ots)
- {
- fscanf (ots, "%u", &old_timestamp);
- fclose (ots);
- if (old_timestamp && setup_timestamp
- && (old_timestamp > setup_timestamp))
+ if (yyparse () || error_count > 0)
+ MessageBox (0, error_buf,
+ error_count == 1 ? "Parse Error" : "Parse Errors", 0);
+ else
+ {
+ /* save known-good setup.ini locally */
+ String const fp = String ("file://") + local_dir + "/" +
+ rfc1738_escape_part (site_list[n]->url) +
+ "/setup.ini";
+ io_stream::mkpath_p (PATH_TO_FILE, fp);
+ io_stream *inistream = io_stream::open (fp, "wb");
+ if (inistream)
+ {
+ if (compressed_ini_file)
+ {
+ delete ini_file;
+ compressed_ini_file->seek (0, IO_SEEK_SET);
+ ini_file = compress::decompress (compressed_ini_file);
+ }
+ else
+ ini_file->seek (0, IO_SEEK_SET);
+ if (io_stream::copy (ini_file, inistream))
+ io_stream::remove (fp);
+ delete inistream;
+ }
+ ++ini_count;
+ }
+ if (aBuilder.timestamp > setup_timestamp)
{
- int yn = yesno (IDS_OLD_SETUPINI);
- if (yn == IDNO)
- ExitProcess (0);
+ setup_timestamp = aBuilder.timestamp;
+ setup_version = aBuilder.version;
}
+ delete ini_file;
+ delete compressed_ini_file;
+ }
+ return ini_count;
+}
+
+static void
+do_ini_thread (HINSTANCE h, HWND owner)
+{
+ size_t ini_count = 0;
+ if (source == IDC_SOURCE_CWD)
+ ini_count = do_local_ini (owner);
+ else
+ ini_count = do_remote_ini (owner);
+
+ if (ini_count == 0)
+ {
+ next_dialog = source == IDC_SOURCE_CWD ? IDD_S_FROM_CWD : IDD_SITE;
+ return;
}
- if (setup_timestamp)
+
+ if (get_root_dir ().cstr_oneuse())
{
- FILE *nts = fopen (concat (root_dir, "/etc/setup/timestamp", 0), "wt");
- if (nts)
+ io_stream::mkpath_p (PATH_TO_DIR, "cygfile:///etc/setup");
+
+ unsigned int old_timestamp = 0;
+ io_stream *ots =
+ io_stream::open ("cygfile:///etc/setup/timestamp", "rt");
+ if (ots)
+ {
+ char temp[20];
+ memset (temp, '\0', 20);
+ if (ots->read (temp, 19))
+ sscanf (temp, "%u", &old_timestamp);
+ delete ots;
+ if (old_timestamp && setup_timestamp
+ && (old_timestamp > setup_timestamp))
+ {
+ int yn = yesno (owner, IDS_OLD_SETUPINI);
+ if (yn == IDNO)
+ LogSingleton::GetInstance().exit (1);
+ }
+ }
+ if (setup_timestamp)
{
- fprintf (nts, "%u", setup_timestamp);
- fclose (nts);
+ io_stream *nts =
+ io_stream::open ("cygfile:///etc/setup/timestamp", "wt");
+ if (nts)
+ {
+ char temp[20];
+ sprintf (temp, "%u", setup_timestamp);
+ nts->write (temp, strlen (temp));
+ delete nts;
+ }
}
}
- next_dialog = IDD_S_CHOOSE;
+ msg ("setup_version is %s, our_version is %s", setup_version.size() ?
+ setup_version.cstr_oneuse() : "(null)",
+ version);
+ if (setup_version.size())
+ {
+ String ini_version = canonicalize_version (setup_version);
+ String our_version = canonicalize_version (version);
+ // XXX useversion < operator
+ if (our_version.compare (ini_version) < 0)
+ note (owner, IDS_OLD_SETUP_VERSION, version, setup_version.cstr_oneuse());
+ }
+
+ next_dialog = IDD_CHOOSE;
+}
+
+static DWORD WINAPI
+do_ini_thread_reflector(void* p)
+{
+ HANDLE *context;
+ context = (HANDLE*)p;
+
+ do_ini_thread((HINSTANCE)context[0], (HWND)context[1]);
+
+ // Tell the progress page that we're done downloading
+ Progress.PostMessage(WM_APP_SETUP_INI_DOWNLOAD_COMPLETE, 0, next_dialog);
+
+ ExitThread(0);
}
-extern "C" int yyerror (char *s)
+static HANDLE context[2];
+
+void
+do_ini (HINSTANCE h, HWND owner)
+{
+ context[0] = h;
+ context[1] = owner;
+
+ DWORD threadID;
+ CreateThread (NULL, 0, do_ini_thread_reflector, context, 0, &threadID);
+}
+
+
+extern int yylineno;
+extern int yybol ();
+
+extern int
+yyerror (String const &s)
{
- MessageBox (0, s, "Parse Error", 0);
- ExitProcess (0);
+ char buf[MAX_PATH + 1000];
+ int len;
+ sprintf (buf, "%s line %d: ", ini_filename, yylineno - yybol ());
+ sprintf (buf + strlen (buf), s.cstr_oneuse());
+ OutputDebugString (buf);
+ if (error_buf)
+ {
+ strcat (error_buf, "\n");
+ len = strlen (error_buf) + strlen (buf) + 5;
+ error_buf = (char *) realloc (error_buf, len);
+ strcat (error_buf, buf);
+ }
+ else
+ {
+ len = strlen (buf) + 5;
+ error_buf = (char *) malloc (len);
+ strcpy (error_buf, buf);
+ }
+ error_count++;
+ /* TODO: is return 0 correct? */
+ return 0;
}
-extern "C" int fprintf(FILE *f, const char *s, ...);
+extern "C" int fprintf (FILE * f, const char *s, ...);
+
+static char stderrbuf[1000];
int
-fprintf(FILE *f, const char *fmt, ...)
+fprintf (FILE * f, const char *fmt, ...)
{
char buf[1000];
int rv;
if (f == stderr)
{
rv = vsprintf (buf, fmt, args);
- MessageBox (0, buf, "Cygwin Setup", 0);
+ strcat (stderrbuf, buf);
+ if (char *nl = strchr (stderrbuf, '\n'))
+ {
+ *nl = 0;
+ /*OutputDebugString (stderrbuf); */
+ MessageBox (0, buf, "Cygwin Setup", 0);
+ stderrbuf[0] = 0;
+ }
+
}
else
{