public inbox for cygwin-apps@cygwin.com
 help / color / mirror / Atom feed
* [PATCH setup 00/16] Groundwork for a GUI-less installation tool
@ 2024-03-08 18:34 Jon Turney
  2024-03-08 18:34 ` [PATCH setup 01/16] Drop forward declaration of non-existent class IniState Jon Turney
                   ` (15 more replies)
  0 siblings, 16 replies; 17+ messages in thread
From: Jon Turney @ 2024-03-08 18:34 UTC (permalink / raw)
  To: cygwin-apps; +Cc: Jon Turney

This is patch sequence I started sometime in 2020, but only got around to
finishing off recently.

This includes various small tidy-ups, and then lays some groundwork for a
command line installation tool.

At the moment, all this can do is retrieve a (compressed) setup.ini from a
selected mirror and parse it. Package fetching and installation etc. remain
to be looked at.

Jon Turney (16):
  Drop forward declaration of non-existent class IniState
  Move setup_exts[] to the only place it's used
  Split GuiParseFeedback out from ini fetcher
  Split out site into SiteSettings and SitePage
  Don't call Antivirus::AtExit() directly from Logger::exit()
  Simplify invocation of UserSettings::open_settings()
  Split out URL fetching progress reporting
  Instantiate found_ini_list in ini.cc
  Move is_64bit to state
  Move setup.ini pathame components to ini.cc
  Drop hinstance global
  Spit out GetNetAuth from NetIO
  Split out hash checking progress reporting
  Push check_for_cached into package_source
  Put various shared subcomponents into a convenience library
  Add beginnings of a command line installation tool

 AntiVirus.cc                                  |   4 +-
 CliParseFeedback.h                            |  28 --
 Feedback.h                                    |  58 ++++
 GetNetAuth.h                                  |  30 ++
 IniDBBuilderPackage.cc                        |   4 +-
 IniDBBuilderPackage.h                         |   6 +-
 IniParseFeedback.h                            |  38 ---
 LogFile.cc                                    |  18 +-
 LogFile.h                                     |   8 +-
 Makefile.am                                   | 284 ++++++++++--------
 SiteSetting.cc                                | 193 ++++++++++++
 site.h => SiteSetting.h                       |  57 +---
 UserSettings.cc                               |  12 +-
 UserSettings.h                                |   4 +-
 choose.cc                                     |   4 +-
 cli/CliFeedback.h                             |  60 ++++
 cli/CliGetNetAuth.cc                          |  45 +++
 cli/CliGetNetAuth.h                           |  32 ++
 cli/CliGetUrlFeedback.cc                      |  91 ++++++
 cli/CliHashCheckFeedback.cc                   |  30 ++
 .../CliParseFeedback.cc                       |  28 +-
 cli/cyclops.cc                                | 186 ++++++++++++
 crypto.cc                                     |  18 +-
 crypto.h                                      |   9 +-
 dialog.h                                      |   3 -
 download.cc                                   | 121 +-------
 download.h                                    |   6 -
 fromcwd.cc                                    |  11 +-
 geturl.cc                                     | 130 ++------
 geturl.h                                      |  13 +-
 gui/GuiFeedback.h                             |  69 +++++
 gui/GuiGetNetAuth.cc                          | 138 +++++++++
 gui/GuiGetNetAuth.h                           |  38 +++
 gui/GuiGetUrlFeedback.cc                      | 119 ++++++++
 gui/GuiHashCheckFeedback.cc                   |  34 +++
 gui/GuiParseFeedback.cc                       | 149 +++++++++
 site.cc => gui/SitePage.cc                    | 191 +-----------
 gui/SitePage.h                                |  45 +++
 ini.cc                                        | 178 +++--------
 ini.h                                         |  19 +-
 inilex.ll                                     |   6 +-
 inilintmain.cc                                |  10 +-
 install.cc                                    |   6 +-
 main.cc                                       |  50 ++-
 msg.cc                                        |   5 +-
 net.cc                                        |   5 +
 netio.cc                                      | 125 +-------
 netio.h                                       |  19 +-
 nio-ie5.cc                                    |   4 +-
 package_db.cc                                 |   6 +-
 package_db.h                                  |   3 +-
 package_meta.cc                               |  11 +-
 package_meta.h                                |   5 +-
 package_source.cc                             | 126 ++++++--
 package_source.h                              |  12 +-
 splash.cc                                     |   2 +-
 state.cc                                      |   6 +
 state.h                                       |   2 +
 threebar.cc                                   |   2 +-
 59 files changed, 1853 insertions(+), 1063 deletions(-)
 delete mode 100644 CliParseFeedback.h
 create mode 100644 Feedback.h
 create mode 100644 GetNetAuth.h
 delete mode 100644 IniParseFeedback.h
 create mode 100644 SiteSetting.cc
 rename site.h => SiteSetting.h (74%)
 create mode 100644 cli/CliFeedback.h
 create mode 100644 cli/CliGetNetAuth.cc
 create mode 100644 cli/CliGetNetAuth.h
 create mode 100644 cli/CliGetUrlFeedback.cc
 create mode 100644 cli/CliHashCheckFeedback.cc
 rename CliParseFeedback.cc => cli/CliParseFeedback.cc (58%)
 create mode 100644 cli/cyclops.cc
 create mode 100644 gui/GuiFeedback.h
 create mode 100644 gui/GuiGetNetAuth.cc
 create mode 100644 gui/GuiGetNetAuth.h
 create mode 100644 gui/GuiGetUrlFeedback.cc
 create mode 100644 gui/GuiHashCheckFeedback.cc
 create mode 100644 gui/GuiParseFeedback.cc
 rename site.cc => gui/SitePage.cc (75%)
 create mode 100644 gui/SitePage.h

-- 
2.43.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH setup 01/16] Drop forward declaration of non-existent class IniState
  2024-03-08 18:34 [PATCH setup 00/16] Groundwork for a GUI-less installation tool Jon Turney
@ 2024-03-08 18:34 ` Jon Turney
  2024-03-08 18:34 ` [PATCH setup 02/16] Move setup_exts[] to the only place it's used Jon Turney
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Jon Turney @ 2024-03-08 18:34 UTC (permalink / raw)
  To: cygwin-apps; +Cc: Jon Turney

Also: move forward declaration of class io_stream after includes with
other forward declarations.
---
 ini.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/ini.h b/ini.h
index ecc4b78..d4eaf87 100644
--- a/ini.h
+++ b/ini.h
@@ -16,7 +16,6 @@
 #ifndef SETUP_INI_H
 #define SETUP_INI_H
 
-class io_stream;
 #include <string>
 #include <vector>
 
@@ -29,10 +28,11 @@ extern std::string SetupArch;
 extern std::string SetupIniDir;
 extern std::string SetupBaseName;
 
-class IniState;
+class io_stream;
 class IniDBBuilder;
 class IniParseFeedback;
 void ini_init (io_stream *, IniDBBuilder *, IniParseFeedback &);
+
 #define YYSTYPE char *
 
 /* When setup.ini is parsed, the information is stored according to
-- 
2.43.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH setup 02/16] Move setup_exts[] to the only place it's used
  2024-03-08 18:34 [PATCH setup 00/16] Groundwork for a GUI-less installation tool Jon Turney
  2024-03-08 18:34 ` [PATCH setup 01/16] Drop forward declaration of non-existent class IniState Jon Turney
@ 2024-03-08 18:34 ` Jon Turney
  2024-03-08 18:34 ` [PATCH setup 03/16] Split GuiParseFeedback out from ini fetcher Jon Turney
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Jon Turney @ 2024-03-08 18:34 UTC (permalink / raw)
  To: cygwin-apps; +Cc: Jon Turney

---
 ini.cc | 1 +
 ini.h  | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/ini.cc b/ini.cc
index 3ef1311..112a0ad 100644
--- a/ini.cc
+++ b/ini.cc
@@ -58,6 +58,7 @@ extern ThreeBarProgressPage Progress;
 unsigned int setup_timestamp = 0;
 std::string ini_setup_version;
 // TODO: use C++11x initializer lists instead and drop the literal array
+static const std::string setup_exts[] = { "zst", "xz", "bz2", "ini" };
 IniList setup_ext_list (setup_exts,
 			setup_exts + (sizeof(setup_exts) / sizeof(*setup_exts)));
 
diff --git a/ini.h b/ini.h
index d4eaf87..4088968 100644
--- a/ini.h
+++ b/ini.h
@@ -21,7 +21,7 @@
 
 typedef std::vector <std::string> IniList;
 extern IniList found_ini_list, setup_ext_list;
-const std::string setup_exts[] = { "zst", "xz", "bz2", "ini" };
+
 extern bool is_64bit;
 extern bool is_new_install;
 extern std::string SetupArch;
-- 
2.43.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH setup 03/16] Split GuiParseFeedback out from ini fetcher
  2024-03-08 18:34 [PATCH setup 00/16] Groundwork for a GUI-less installation tool Jon Turney
  2024-03-08 18:34 ` [PATCH setup 01/16] Drop forward declaration of non-existent class IniState Jon Turney
  2024-03-08 18:34 ` [PATCH setup 02/16] Move setup_exts[] to the only place it's used Jon Turney
@ 2024-03-08 18:34 ` Jon Turney
  2024-03-08 18:34 ` [PATCH setup 04/16] Split out site into SiteSettings and SitePage Jon Turney
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Jon Turney @ 2024-03-08 18:34 UTC (permalink / raw)
  To: cygwin-apps; +Cc: Jon Turney

This will ultimately make it possible to fetch and parse an ini file
without having a GUI.
---
 Makefile.am             |   1 +
 gui/GuiParseFeedback.cc | 139 ++++++++++++++++++++++++++++++++++++++++
 ini.cc                  | 134 ++------------------------------------
 ini.h                   |   2 +
 4 files changed, 149 insertions(+), 127 deletions(-)
 create mode 100644 gui/GuiParseFeedback.cc

diff --git a/Makefile.am b/Makefile.am
index 8a50cb0..82efbd8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -180,6 +180,7 @@ endif
 	geturl.h \
 	gpg-packet.cc \
 	gpg-packet.h \
+	gui/GuiParseFeedback.cc \
 	ini.cc \
 	ini.h \
 	IniDBBuilder.h \
diff --git a/gui/GuiParseFeedback.cc b/gui/GuiParseFeedback.cc
new file mode 100644
index 0000000..263fae1
--- /dev/null
+++ b/gui/GuiParseFeedback.cc
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2000,2007 Red Hat, Inc.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     A copy of the GNU General Public License can be found at
+ *     http://www.gnu.org/
+ *
+ * Written by DJ Delorie <dj@cygnus.com>
+ *
+ */
+
+#include "Exception.h"
+#include "IniParseFeedback.h"
+#include "ini.h"
+#include "msg.h"
+#include "resource.h"
+#include "state.h"
+#include "threebar.h"
+
+extern ThreeBarProgressPage Progress;
+
+class GuiParseFeedback : public IniParseFeedback
+{
+public:
+  GuiParseFeedback () : lastpct (0)
+    {
+      Progress.SetText1 (IDS_PROGRESS_PARSING);
+      Progress.SetText2 ("");
+      Progress.SetText3 ("");
+      Progress.SetText4 (IDS_PROGRESS_PROGRESS);
+
+      yyerror_count = 0;
+      yyerror_messages.clear ();
+    }
+  virtual void progress (unsigned long const pos, unsigned long const max)
+    {
+      if (!max)
+        /* length not known or eof */
+        return;
+      if (lastpct == 100)
+        /* rounding down should mean this only ever fires once */
+        lastpct = 0;
+      if (pos * 100 / max > lastpct)
+        {
+          lastpct = pos * 100 / max;
+          /* Log (LOG_BABBLE) << lastpct << "% (" << pos << " of " << max
+            << " bytes of ini file read)" << endLog; */
+        }
+      Progress.SetBar1 (pos, max);
+
+      static char buf[100];
+      sprintf (buf, "%d %%  (%ldk/%ldk)", lastpct, pos/1000, max/1000);
+      Progress.SetText3 (buf);
+    }
+  virtual void iniName (const std::string& name)
+    {
+      Progress.SetText2 (name.c_str ());
+      Progress.SetText3 ("");
+      filename = name;
+    }
+  virtual void babble (const std::string& message)const
+    {
+      Log (LOG_BABBLE) << message << endLog;
+    }
+  virtual void warning (const std::string& message)const
+    {
+      mbox (Progress.GetHWND(), message.c_str (), "Warning", 0);
+    }
+  virtual void note_error(int lineno, const std::string &error)
+    {
+      char tmp[16];
+      sprintf (tmp, "%d", lineno);
+
+      std::string e = filename + " line " + tmp + ": " + error;
+
+      if (!yyerror_messages.empty ())
+        yyerror_messages += "\n";
+
+      yyerror_messages += e;
+      yyerror_count++;
+    }
+  virtual bool has_errors () const
+    {
+      return (yyerror_count > 0);
+    }
+  virtual void show_errors () const
+    {
+      mbox (Progress.GetHWND(), yyerror_messages.c_str (), "Parse Errors", 0);
+    }
+  virtual ~ GuiParseFeedback ()
+    {
+      Progress.SetText2 ("");
+      Progress.SetText3 ("");
+      Progress.SetText4 (IDS_PROGRESS_PACKAGE);
+      Progress.SetBar1 (0);
+    }
+private:
+  unsigned int lastpct;
+  std::string filename;
+  std::string yyerror_messages;
+  int yyerror_count;
+};
+
+static DWORD WINAPI
+do_ini_thread_reflector (void* p)
+{
+  HANDLE *context;
+  context = (HANDLE*)p;
+
+  SetThreadUILanguage(langid);
+
+  try
+  {
+    GuiParseFeedback feedback;
+    bool succeeded = do_ini_thread ((HINSTANCE)context[0], (HWND)context[1], feedback);
+
+    // Tell the progress page that we're done downloading
+    Progress.PostMessageNow (WM_APP_SETUP_INI_DOWNLOAD_COMPLETE, 0, succeeded);
+  }
+  TOPLEVEL_CATCH ((HWND) context[1], "ini");
+
+  ExitThread (0);
+}
+
+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);
+}
diff --git a/ini.cc b/ini.cc
index 112a0ad..95c9964 100644
--- a/ini.cc
+++ b/ini.cc
@@ -33,7 +33,6 @@
 #include <process.h>
 
 #include "resource.h"
-#include "state.h"
 #include "geturl.h"
 #include "dialog.h"
 #include "mount.h"
@@ -44,17 +43,13 @@
 #include "io_stream.h"
 #include "io_stream_memory.h"
 
-#include "threebar.h"
-
 #include "getopt++/BoolOption.h"
 #include "IniDBBuilderPackage.h"
 #include "compress.h"
-#include "Exception.h"
+#include "msg.h"
 #include "crypto.h"
 #include "package_db.h"
 
-extern ThreeBarProgressPage Progress;
-
 unsigned int setup_timestamp = 0;
 std::string ini_setup_version;
 // TODO: use C++11x initializer lists instead and drop the literal array
@@ -65,87 +60,6 @@ IniList setup_ext_list (setup_exts,
 static BoolOption NoVerifyOption (false, 'X', "no-verify", IDS_HELPTEXT_NO_VERIFY);
 static BoolOption NoVersionCheckOption (false, '\0', "no-version-check", IDS_HELPTEXT_NO_VERSION_CHECK);
 
-class GuiParseFeedback : public IniParseFeedback
-{
-public:
-  GuiParseFeedback () : lastpct (0)
-    {
-      Progress.SetText1 (IDS_PROGRESS_PARSING);
-      Progress.SetText2 ("");
-      Progress.SetText3 ("");
-      Progress.SetText4 (IDS_PROGRESS_PROGRESS);
-
-      yyerror_count = 0;
-      yyerror_messages.clear ();
-    }
-  virtual void progress (unsigned long const pos, unsigned long const max)
-    {
-      if (!max)
-	/* length not known or eof */
-	return;
-      if (lastpct == 100)
-	/* rounding down should mean this only ever fires once */
-	lastpct = 0;
-      if (pos * 100 / max > lastpct)
-	{
-	  lastpct = pos * 100 / max;
-	  /* Log (LOG_BABBLE) << lastpct << "% (" << pos << " of " << max
-	    << " bytes of ini file read)" << endLog; */
-	}
-      Progress.SetBar1 (pos, max);
-
-      static char buf[100];
-      sprintf (buf, "%d %%  (%ldk/%ldk)", lastpct, pos/1000, max/1000);
-      Progress.SetText3 (buf);
-    }
-  virtual void iniName (const std::string& name)
-    {
-      Progress.SetText2 (name.c_str ());
-      Progress.SetText3 ("");
-      filename = name;
-    }
-  virtual void babble (const std::string& message)const
-    {
-      Log (LOG_BABBLE) << message << endLog;
-    }
-  virtual void warning (const std::string& message)const
-    {
-      mbox (Progress.GetHWND(), message.c_str (), "Warning", 0);
-    }
-  virtual void note_error(int lineno, const std::string &error)
-    {
-      char tmp[16];
-      sprintf (tmp, "%d", lineno);
-
-      std::string e = filename + " line " + tmp + ": " + error;
-
-      if (!yyerror_messages.empty ())
-        yyerror_messages += "\n";
-
-      yyerror_messages += e;
-      yyerror_count++;
-    }
-  virtual bool has_errors () const
-    {
-      return (yyerror_count > 0);
-    }
-  virtual void show_errors () const
-    {
-      mbox (Progress.GetHWND(), yyerror_messages.c_str (), "Parse Errors", 0);
-    }
-  virtual ~ GuiParseFeedback ()
-    {
-      Progress.SetText2 ("");
-      Progress.SetText3 ("");
-      Progress.SetText4 (IDS_PROGRESS_PACKAGE);
-      Progress.SetBar1 (0);
-    }
-private:
-  unsigned int lastpct;
-  std::string filename;
-  std::string yyerror_messages;
-  int yyerror_count;
-};
 
 static io_stream*
 decompress_ini (io_stream *ini_file, std::string &current_ini_name)
@@ -231,7 +145,7 @@ check_ini_sig (io_stream* ini_file, io_stream* ini_sig_file,
 }
 
 static bool
-do_local_ini (HWND owner)
+do_local_ini (HWND owner, IniParseFeedback &myFeedback)
 {
   bool ini_error = false;
   io_stream *ini_file, *ini_sig_file;
@@ -239,7 +153,6 @@ do_local_ini (HWND owner)
   for (IniList::const_iterator n = found_ini_list.begin ();
        n != found_ini_list.end (); ++n)
     {
-      GuiParseFeedback myFeedback;
       IniDBBuilderPackage aBuilder (myFeedback);
       bool sig_fail = false;
       std::string current_ini_ext, current_ini_name, current_ini_sig_name;
@@ -290,7 +203,7 @@ do_local_ini (HWND owner)
 }
 
 static bool
-do_remote_ini (HWND owner)
+do_remote_ini (HWND owner, IniParseFeedback &myFeedback)
 {
   bool ini_error = false;
   io_stream *ini_file = NULL, *ini_sig_file;
@@ -302,7 +215,6 @@ do_remote_ini (HWND owner)
   for (SiteList::const_iterator n = site_list.begin ();
        n != site_list.end (); ++n)
     {
-      GuiParseFeedback myFeedback;
       IniDBBuilderPackage aBuilder (myFeedback);
       bool sig_fail = false;
       std::string current_ini_ext, current_ini_name, current_ini_sig_name;
@@ -369,8 +281,8 @@ do_remote_ini (HWND owner)
   return ini_error;
 }
 
-static bool
-do_ini_thread (HINSTANCE h, HWND owner)
+bool
+do_ini_thread (HINSTANCE h, HWND owner, IniParseFeedback &feedback)
 {
   packagedb db;
   db.init();
@@ -378,9 +290,9 @@ do_ini_thread (HINSTANCE h, HWND owner)
   bool ini_error = true;
 
   if (source == IDC_SOURCE_LOCALDIR)
-    ini_error = do_local_ini (owner);
+    ini_error = do_local_ini (owner, feedback);
   else
-    ini_error = do_remote_ini (owner);
+    ini_error = do_remote_ini (owner, feedback);
 
   if (ini_error)
     return false;
@@ -434,35 +346,3 @@ do_ini_thread (HINSTANCE h, HWND owner)
 
   return true;
 }
-
-static DWORD WINAPI
-do_ini_thread_reflector (void* p)
-{
-  HANDLE *context;
-  context = (HANDLE*)p;
-
-  SetThreadUILanguage(langid);
-
-  try
-  {
-    bool succeeded = do_ini_thread ((HINSTANCE)context[0], (HWND)context[1]);
-
-    // Tell the progress page that we're done downloading
-    Progress.PostMessageNow (WM_APP_SETUP_INI_DOWNLOAD_COMPLETE, 0, succeeded);
-  }
-  TOPLEVEL_CATCH ((HWND) context[1], "ini");
-
-  ExitThread (0);
-}
-
-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);
-}
diff --git a/ini.h b/ini.h
index 4088968..6b24211 100644
--- a/ini.h
+++ b/ini.h
@@ -16,6 +16,7 @@
 #ifndef SETUP_INI_H
 #define SETUP_INI_H
 
+#include "win32.h"
 #include <string>
 #include <vector>
 
@@ -32,6 +33,7 @@ class io_stream;
 class IniDBBuilder;
 class IniParseFeedback;
 void ini_init (io_stream *, IniDBBuilder *, IniParseFeedback &);
+bool do_ini_thread (HINSTANCE h, HWND owner, IniParseFeedback &feedback);
 
 #define YYSTYPE char *
 
-- 
2.43.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH setup 04/16] Split out site into SiteSettings and SitePage
  2024-03-08 18:34 [PATCH setup 00/16] Groundwork for a GUI-less installation tool Jon Turney
                   ` (2 preceding siblings ...)
  2024-03-08 18:34 ` [PATCH setup 03/16] Split GuiParseFeedback out from ini fetcher Jon Turney
@ 2024-03-08 18:34 ` Jon Turney
  2024-03-08 18:34 ` [PATCH setup 05/16] Don't call Antivirus::AtExit() directly from Logger::exit() Jon Turney
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Jon Turney @ 2024-03-08 18:34 UTC (permalink / raw)
  To: cygwin-apps; +Cc: Jon Turney

Again, this will ultimately make it possible to specify, or store and
retrieve from settings a site, without having a GUI.
---
 Makefile.am                |   6 +-
 SiteSetting.cc             | 193 +++++++++++++++++++++++++++++++++++++
 site.h => SiteSetting.h    |  57 +++--------
 site.cc => gui/SitePage.cc | 169 +-------------------------------
 gui/SitePage.h             |  45 +++++++++
 ini.cc                     |   2 +-
 main.cc                    |   3 +-
 threebar.cc                |   2 +-
 8 files changed, 264 insertions(+), 213 deletions(-)
 create mode 100644 SiteSetting.cc
 rename site.h => SiteSetting.h (74%)
 rename site.cc => gui/SitePage.cc (77%)
 create mode 100644 gui/SitePage.h

diff --git a/Makefile.am b/Makefile.am
index 82efbd8..f753961 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -266,8 +266,10 @@ endif
 	setup_version.c \
 	sha2.h \
 	sha2.c \
-	site.cc \
-	site.h \
+	gui/SitePage.cc \
+	gui/SitePage.h \
+	SiteSetting.cc \
+	SiteSetting.h \
 	source.cc \
 	source.h \
 	SourceSetting.cc \
diff --git a/SiteSetting.cc b/SiteSetting.cc
new file mode 100644
index 0000000..be5f5d8
--- /dev/null
+++ b/SiteSetting.cc
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2000, Red Hat, Inc.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     A copy of the GNU General Public License can be found at
+ *     http://www.gnu.org/
+ *
+ * Written by DJ Delorie <dj@cygnus.com>
+ *
+ */
+
+#include "io_stream.h"
+#include "SiteSetting.h"
+#include "UserSettings.h"
+#include "getopt++/StringArrayOption.h"
+#include "getopt++/BoolOption.h"
+#include "resource.h"
+
+#include <algorithm>
+#include <string>
+#include <vector>
+#include <string.h>
+
+StringArrayOption SiteOption('s', "site", IDS_HELPTEXT_SITE);
+extern BoolOption UnsupportedOption;
+
+/* Selected sites */
+SiteList site_list;
+
+/* Fresh mirrors + selected sites */
+SiteList all_site_list;
+
+SiteSetting::SiteSetting (): saved (false)
+{
+  std::vector<std::string> SiteOptionStrings = SiteOption;
+  if (SiteOptionStrings.size())
+    {
+      for (std::vector<std::string>::const_iterator n = SiteOptionStrings.begin ();
+           n != SiteOptionStrings.end (); ++n)
+        registerSavedSite (n->c_str ());
+    }
+  else
+    getSavedSites ();
+}
+
+const char *
+SiteSetting::lastMirrorKey ()
+{
+  if (UnsupportedOption)
+    return "last-mirror-unsupported";
+
+  return "last-mirror";
+}
+
+void
+SiteSetting::save()
+{
+  io_stream *f = UserSettings::instance().open (lastMirrorKey ());
+  if (f)
+    {
+      for (SiteList::const_iterator n = site_list.begin ();
+           n != site_list.end (); ++n)
+        *f << n->url;
+      delete f;
+    }
+  saved = true;
+}
+
+SiteSetting::~SiteSetting ()
+{
+  if (!saved)
+    save ();
+}
+
+/* List of machines that should not be used by default when saved
+   in "last-mirror". */
+#define NOSAVE1 "ftp://sourceware.org/"
+#define NOSAVE1_LEN (sizeof (NOSAVE2) - 1)
+#define NOSAVE2 "ftp://sources.redhat.com/"
+#define NOSAVE2_LEN (sizeof (NOSAVE1) - 1)
+#define NOSAVE3 "ftp://gcc.gnu.org/"
+#define NOSAVE3_LEN (sizeof (NOSAVE3) - 1)
+
+void
+SiteSetting::registerSavedSite (const char * site)
+{
+  site_list_type tempSite(site, "", "", "", false);
+
+  /* Don't default to certain machines if they suffer from bandwidth
+     limitations. */
+  if (strnicmp (site, NOSAVE1, NOSAVE1_LEN) == 0
+      || strnicmp (site, NOSAVE2, NOSAVE2_LEN) == 0
+      || strnicmp (site, NOSAVE3, NOSAVE3_LEN) == 0)
+    return;
+
+  site_list_insert (all_site_list, tempSite);
+  site_list.push_back (tempSite);
+}
+
+void
+SiteSetting::getSavedSites ()
+{
+  const char *buf = UserSettings::instance().get (lastMirrorKey ());
+  if (!buf)
+    return;
+  char *fg_ret = strdup (buf);
+  for (char *site = strtok (fg_ret, "\n"); site; site = strtok (NULL, "\n"))
+    registerSavedSite (site);
+  free (fg_ret);
+}
+
+site_list_type::site_list_type (const std::string &_url,
+                                const std::string &_servername,
+                                const std::string &_area,
+                                const std::string &_location,
+                                bool _from_mirrors_lst,
+                                bool _noshow /* default: false */)
+{
+  url = _url;
+  servername = _servername;
+  area = _area;
+  location = _location;
+  from_mirrors_lst = _from_mirrors_lst;
+  noshow = _noshow;
+
+  /* Canonicalize URL to ensure it ends with a '/' */
+  if (url.at(url.length()-1) != '/')
+    url.append("/");
+
+  /* displayed_url is protocol and site name part of url */
+  std::string::size_type path_offset = url.find ("/", url.find ("//") + 2);
+  displayed_url = url.substr(0, path_offset);
+
+  /* the sorting key is hostname components in reverse order (to sort by country code)
+     plus the url (to ensure uniqueness) */
+  key = std::string();
+  std::string::size_type last_idx = displayed_url.length () - 1;
+  std::string::size_type idx = url.find_last_of("./", last_idx);
+  if (last_idx - idx == 3)
+  {
+    /* Sort non-country TLDs (.com, .net, ...) together. */
+    key += " ";
+  }
+  do
+  {
+    key += url.substr(idx + 1, last_idx - idx);
+    key += " ";
+    last_idx = idx - 1;
+    idx = url.find_last_of("./", last_idx);
+    if (idx == std::string::npos)
+      idx = 0;
+  } while (idx > 0);
+  key += url;
+}
+
+bool
+site_list_type::operator == (site_list_type const &rhs) const
+{
+  return stricmp (key.c_str(), rhs.key.c_str()) == 0;
+}
+
+bool
+site_list_type::operator < (site_list_type const &rhs) const
+{
+  return stricmp (key.c_str(), rhs.key.c_str()) < 0;
+}
+
+/*
+  A SiteList is maintained as an in-order std::vector of site_list_type, by
+  replacing it with a new object with the new item inserted in the correct
+  place.
+
+  Yes, we could just use an ordered container, instead.
+*/
+void
+site_list_insert(SiteList &site_list, site_list_type newsite)
+{
+  SiteList::iterator i = find (site_list.begin(), site_list.end(), newsite);
+  if (i == site_list.end())
+    {
+      SiteList result;
+      merge (site_list.begin(), site_list.end(),
+             &newsite, &newsite + 1,
+             inserter (result, result.begin()));
+      site_list = result;
+    }
+  else
+    *i = newsite;
+}
diff --git a/site.h b/SiteSetting.h
similarity index 74%
rename from site.h
rename to SiteSetting.h
index 6ec7cf3..0582a2e 100644
--- a/site.h
+++ b/SiteSetting.h
@@ -13,44 +13,30 @@
  *
  */
 
-#ifndef SETUP_SITE_H
-#define SETUP_SITE_H
+#ifndef SETUP_SITESETTING_H
+#define SETUP_SITESETTING_H
 
-#include <string>
 #include <vector>
 
-#include "proppage.h"
-
-class SitePage : public PropertyPage
+class SiteSetting
 {
-public:
-  SitePage ();
-  virtual ~ SitePage ()
-  {
-  };
-
-  bool Create ();
-
-  virtual void OnInit ();
-  virtual void OnActivate ();
-  virtual long OnNext ();
-  virtual long OnBack ();
-  virtual long OnUnattended ();
-
-  virtual bool OnMessageCmd (int id, HWND hwndctl, UINT code);
-
-  void PopulateListBox();
-  void CheckControlsAndDisableAccordingly () const;
+  public:
+    SiteSetting ();
+    void save ();
+    ~SiteSetting ();
+  private:
+    bool saved;
+    void getSavedSites();
+    void registerSavedSite(char const *);
+    const char *lastMirrorKey();
 };
 
-void do_download_site_info (HINSTANCE h, HWND owner);
-
 class site_list_type
 {
 public:
   site_list_type () : url (), displayed_url (), key () {};
   site_list_type (const std::string& , const std::string& ,
-                  const std::string& , const std::string&, bool, bool);
+                  const std::string& , const std::string&, bool, bool = false);
   ~site_list_type () {};
   std::string url;
   // provided by mirrors.lst but not used
@@ -74,22 +60,11 @@ public:
 
 typedef std::vector <site_list_type> SiteList;
 
+void site_list_insert(SiteList &site_list, site_list_type newsite);
+
 /* user chosen sites */
 extern SiteList site_list;
 /* potential sites */
 extern SiteList all_site_list;
 
-class SiteSetting
-{
-  public:
-    SiteSetting ();
-    void save ();
-    ~SiteSetting ();
-  private:
-    bool saved;
-    void getSavedSites();
-    void registerSavedSite(char const *);
-    const char *lastMirrorKey();
-};
-
-#endif /* SETUP_SITE_H */
+#endif /* SETUP_SITESETTING_H */
diff --git a/site.cc b/gui/SitePage.cc
similarity index 77%
rename from site.cc
rename to gui/SitePage.cc
index 569235a..69bac1d 100644
--- a/site.cc
+++ b/gui/SitePage.cc
@@ -19,7 +19,6 @@
 #include <string>
 #include <algorithm>
 
-#include "site.h"
 #include "win32.h"
 #include <stdio.h>
 #include <stdlib.h>
@@ -32,7 +31,7 @@
 #include "msg.h"
 #include "LogSingleton.h"
 #include "io_stream.h"
-#include "site.h"
+#include "gui/SitePage.h"
 
 #include "propsheet.h"
 
@@ -71,19 +70,14 @@ SitePage::SitePage ()
   sizeProcessor.AddControlInfo (SiteControlsInfo);
 }
 
-#include "getopt++/StringArrayOption.h"
 #include "getopt++/BoolOption.h"
 #include "UserSettings.h"
+#include "SiteSetting.h"
 
 bool cache_is_usable;
 bool cache_needs_writing;
 std::string cache_warn_urls;
 
-/* Selected sites */
-SiteList site_list;
-
-/* Fresh mirrors + selected sites */
-SiteList all_site_list;
 
 /* Previously fresh + cached before */
 SiteList cached_site_list;
@@ -91,131 +85,9 @@ SiteList cached_site_list;
 /* Stale selected sites to warn about and add to cache */
 SiteList dropped_site_list;
 
-StringArrayOption SiteOption('s', "site", IDS_HELPTEXT_SITE);
 BoolOption OnlySiteOption(false, 'O', "only-site", IDS_HELPTEXT_ONLY_SITE);
 extern BoolOption UnsupportedOption;
 
-SiteSetting::SiteSetting (): saved (false)
-{
-  std::vector<std::string> SiteOptionStrings = SiteOption;
-  if (SiteOptionStrings.size())
-    {
-      for (std::vector<std::string>::const_iterator n = SiteOptionStrings.begin ();
-	   n != SiteOptionStrings.end (); ++n)
-	registerSavedSite (n->c_str ());
-    }
-  else
-    getSavedSites ();
-}
-
-const char *
-SiteSetting::lastMirrorKey ()
-{
-  if (UnsupportedOption)
-    return "last-mirror-unsupported";
-
-  return "last-mirror";
-}
-
-void 
-SiteSetting::save()
-{
-  io_stream *f = UserSettings::instance().open (lastMirrorKey ());
-  if (f)
-    {
-      for (SiteList::const_iterator n = site_list.begin ();
-	   n != site_list.end (); ++n)
-	*f << n->url;
-      delete f;
-    }
-  saved = true;
-}
-
-SiteSetting::~SiteSetting ()
-{
-  if (!saved)
-    save ();
-}
-
-site_list_type::site_list_type (const std::string &_url,
-				const std::string &_servername,
-				const std::string &_area,
-				const std::string &_location,
-				bool _from_mirrors_lst,
-                                bool _noshow = false)
-{
-  url = _url;
-  servername = _servername;
-  area = _area;
-  location = _location;
-  from_mirrors_lst = _from_mirrors_lst;
-  noshow = _noshow;
-
-  /* Canonicalize URL to ensure it ends with a '/' */
-  if (url.at(url.length()-1) != '/')
-    url.append("/");
-
-  /* displayed_url is protocol and site name part of url */
-  std::string::size_type path_offset = url.find ("/", url.find ("//") + 2);
-  displayed_url = url.substr(0, path_offset);
-
-  /* the sorting key is hostname components in reverse order (to sort by country code)
-     plus the url (to ensure uniqueness) */
-  key = std::string();
-  std::string::size_type last_idx = displayed_url.length () - 1;
-  std::string::size_type idx = url.find_last_of("./", last_idx);
-  if (last_idx - idx == 3)
-  {
-    /* Sort non-country TLDs (.com, .net, ...) together. */
-    key += " ";
-  }
-  do
-  {
-    key += url.substr(idx + 1, last_idx - idx);
-    key += " ";
-    last_idx = idx - 1;
-    idx = url.find_last_of("./", last_idx);
-    if (idx == std::string::npos)
-      idx = 0;
-  } while (idx > 0);
-  key += url;
-}
-
-bool
-site_list_type::operator == (site_list_type const &rhs) const
-{
-  return stricmp (key.c_str(), rhs.key.c_str()) == 0; 
-}
-
-bool
-site_list_type::operator < (site_list_type const &rhs) const
-{
-  return stricmp (key.c_str(), rhs.key.c_str()) < 0; 
-}
-
-/*
-  A SiteList is maintained as an in-order std::vector of site_list_type, by
-  replacing it with a new object with the new item inserted in the correct
-  place.
-
-  Yes, we could just use an ordered container, instead.
-*/
-static void
-site_list_insert(SiteList &site_list, site_list_type newsite)
-{
-  SiteList::iterator i = find (site_list.begin(), site_list.end(), newsite);
-  if (i == site_list.end())
-    {
-      SiteList result;
-      merge (site_list.begin(), site_list.end(),
-             &newsite, &newsite + 1,
-             inserter (result, result.begin()));
-      site_list = result;
-    }
-  else
-    *i = newsite;
-}
-
 static void
 save_dialog (HWND h)
 {
@@ -381,43 +253,6 @@ get_site_list (HINSTANCE h, HWND owner)
   return 0;
 }
 
-/* List of machines that should not be used by default when saved
-   in "last-mirror". */
-#define NOSAVE1 "ftp://sourceware.org/"
-#define NOSAVE1_LEN (sizeof (NOSAVE2) - 1)
-#define NOSAVE2 "ftp://sources.redhat.com/"
-#define NOSAVE2_LEN (sizeof (NOSAVE1) - 1)
-#define NOSAVE3 "ftp://gcc.gnu.org/"
-#define NOSAVE3_LEN (sizeof (NOSAVE3) - 1)
-
-void
-SiteSetting::registerSavedSite (const char * site)
-{
-  site_list_type tempSite(site, "", "", "", false);
-
-  /* Don't default to certain machines if they suffer from bandwidth
-     limitations. */
-  if (strnicmp (site, NOSAVE1, NOSAVE1_LEN) == 0
-      || strnicmp (site, NOSAVE2, NOSAVE2_LEN) == 0
-      || strnicmp (site, NOSAVE3, NOSAVE3_LEN) == 0)
-    return;
-
-  site_list_insert (all_site_list, tempSite);
-  site_list.push_back (tempSite);
-}
-
-void
-SiteSetting::getSavedSites ()
-{
-  const char *buf = UserSettings::instance().get (lastMirrorKey ());
-  if (!buf)
-    return;
-  char *fg_ret = strdup (buf);
-  for (char *site = strtok (fg_ret, "\n"); site; site = strtok (NULL, "\n"))
-    registerSavedSite (site);
-  free (fg_ret);
-}
-
 static DWORD WINAPI
 do_download_site_info_thread (void *p)
 {
diff --git a/gui/SitePage.h b/gui/SitePage.h
new file mode 100644
index 0000000..1208338
--- /dev/null
+++ b/gui/SitePage.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2001, Robert Collins.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     A copy of the GNU General Public License can be found at
+ *     http://www.gnu.org/
+ *
+ * Written by Robert Collins <rbtcollins@hotmail.com>
+ *
+ */
+
+#ifndef SETUP_SITE_H
+#define SETUP_SITE_H
+
+#include "proppage.h"
+
+class SitePage : public PropertyPage
+{
+public:
+  SitePage ();
+  virtual ~ SitePage ()
+  {
+  };
+
+  bool Create ();
+
+  virtual void OnInit ();
+  virtual void OnActivate ();
+  virtual long OnNext ();
+  virtual long OnBack ();
+  virtual long OnUnattended ();
+
+  virtual bool OnMessageCmd (int id, HWND hwndctl, UINT code);
+
+  void PopulateListBox();
+  void CheckControlsAndDisableAccordingly () const;
+};
+
+void do_download_site_info (HINSTANCE h, HWND owner);
+
+#endif /* SETUP_SITE_H */
diff --git a/ini.cc b/ini.cc
index 95c9964..3d3cbde 100644
--- a/ini.cc
+++ b/ini.cc
@@ -36,7 +36,7 @@
 #include "geturl.h"
 #include "dialog.h"
 #include "mount.h"
-#include "site.h"
+#include "SiteSetting.h"
 #include "find.h"
 #include "IniParseFeedback.h"
 
diff --git a/main.cc b/main.cc
index cf9e323..2ce3b30 100644
--- a/main.cc
+++ b/main.cc
@@ -53,7 +53,7 @@
 #include "root.h"
 #include "localdir.h"
 #include "net.h"
-#include "site.h"
+#include "gui/SitePage.h"
 #include "choose.h"
 #include "prereq.h"
 #include "confirm.h"
@@ -74,6 +74,7 @@
 #include "SourceSetting.h"
 #include "ConnectionSetting.h"
 #include "KeysSetting.h"
+#include "SiteSetting.h"
 
 #include <wincon.h>
 #include <fstream>
diff --git a/threebar.cc b/threebar.cc
index bc356c0..16430bb 100644
--- a/threebar.cc
+++ b/threebar.cc
@@ -23,7 +23,7 @@
 #include "resource.h"
 
 #include "dialog.h"
-#include "site.h"
+#include "gui/SitePage.h"
 
 #include "propsheet.h"
 #include "threebar.h"
-- 
2.43.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH setup 05/16] Don't call Antivirus::AtExit() directly from Logger::exit()
  2024-03-08 18:34 [PATCH setup 00/16] Groundwork for a GUI-less installation tool Jon Turney
                   ` (3 preceding siblings ...)
  2024-03-08 18:34 ` [PATCH setup 04/16] Split out site into SiteSettings and SitePage Jon Turney
@ 2024-03-08 18:34 ` Jon Turney
  2024-03-08 18:34 ` [PATCH setup 06/16] Simplify invocation of UserSettings::open_settings() Jon Turney
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Jon Turney @ 2024-03-08 18:34 UTC (permalink / raw)
  To: cygwin-apps; +Cc: Jon Turney

The call to Antivirus::AtExit() needs to be take place before we write
the log, so we see in the log if it failed. But calling it directly from
Logger::exit() is a horrible layering violation, which makes it
impossible to use the logger in other executables...

Add LogFile::atexit() method, which registers atexit handlers which are
run by LogFile::exit() before the log is closed.

The real solution here is probably not to exit via Logger::exit() all
over the place. And also perhaps to switch logfile writing from
"defered" to "immediate" once the root directory has been selected
(which establishes where the logfile should be written).

Also update a comment, out of date since 5fa64c3c.
---
 AntiVirus.cc |  4 ++--
 LogFile.cc   | 18 +++++++++++++-----
 LogFile.h    |  8 ++++++--
 3 files changed, 21 insertions(+), 9 deletions(-)

diff --git a/AntiVirus.cc b/AntiVirus.cc
index cc416cc..cb8e8ee 100644
--- a/AntiVirus.cc
+++ b/AntiVirus.cc
@@ -16,8 +16,7 @@
 #include "AntiVirus.h"
 
 #include "getopt++/BoolOption.h"
-
-#include "LogSingleton.h"
+#include "LogFile.h"
 
 #include "win32.h"
 #include <stdio.h>
@@ -77,6 +76,7 @@ bool
 AntiVirusPage::Create ()
 {
     detect();
+    Logger().atexit(AntiVirus::AtExit);
     return PropertyPage::Create (NULL, dialog_cmd, IDD_VIRUS);
 }
 
diff --git a/LogFile.cc b/LogFile.cc
index ab2e3ec..0022eff 100644
--- a/LogFile.cc
+++ b/LogFile.cc
@@ -28,7 +28,6 @@
 #include <time.h>
 #include <string>
 #include <stdexcept>
-#include "AntiVirus.h"
 #include "filemanip.h"
 #include "String++.h"
 #include "getopt++/BoolOption.h"
@@ -115,12 +114,21 @@ LogFile::getFileName (int level) const
   return "<no log was in use>";
 }
 
+void
+LogFile::atexit(void (*func)(void))
+{
+  exit_fns.push_back(func);
+}
+
 void
 LogFile::exit (int exit_code, bool show_end_install_msg)
 {
-  AntiVirus::AtExit();
+  /* Execute any functions we want to run at exit (we don't use stdlib atexit()
+     because we want to allow them to potentially write to the log) */
+  for (auto i = exit_fns.rbegin(); i != exit_fns.rend(); ++i)
+      (*i)();
+
   static int been_here = 0;
-  /* Exitcode -1 is special... */
   if (been_here)
     ::exit (exit_code);
   been_here = 1;
@@ -132,8 +140,8 @@ LogFile::exit (int exit_code, bool show_end_install_msg)
       Log (LOG_PLAIN) << "note: " << wstring_to_string(buf) << endLog;
     }
 
-  /* ... in that it skips the boring log messages.  Exit code -1 is used when
-     just printing the help output and when we're self-elevating. */
+  /* Skip the log messages when just printing the help/version output, and when
+     we're self-elevating. */
   if (show_end_install_msg)
     Log (LOG_TIMESTAMP) << "Ending cygwin install" << endLog;
 
diff --git a/LogFile.h b/LogFile.h
index ddbc2dc..8efa1b0 100644
--- a/LogFile.h
+++ b/LogFile.h
@@ -18,6 +18,7 @@
 
 #include "LogSingleton.h"
 #include <sstream>
+#include <vector>
 
 // Logging class. Default logging level is PLAIN.
 class LogFile : public LogSingleton {
@@ -36,18 +37,21 @@ public:
    * but doesn't call generic C++ destructors
    */
   virtual void exit (int exit_code, bool show_end_install_msg = true)
-	  __attribute__ ((noreturn));
+          __attribute__ ((noreturn));
+  virtual void atexit( void (*func)(void));
+
   virtual void flushAll ();
   virtual ~LogFile();
   // get a specific verbosity stream.
   virtual std::ostream &operator() (enum log_level level);
-  
+
 protected:
   LogFile(std::stringbuf *aStream);
   LogFile (LogFile const &); // no copy constructor
   LogFile &operator = (LogFile const&); // no assignment operator
   virtual void endEntry(); // the current in-progress entry is complete.
   static int exit_msg;
+  std::vector <void (*)(void)> exit_fns;
 private:
   void log_save (int babble, const std::string& filename, bool append);
 };
-- 
2.43.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH setup 06/16] Simplify invocation of UserSettings::open_settings()
  2024-03-08 18:34 [PATCH setup 00/16] Groundwork for a GUI-less installation tool Jon Turney
                   ` (4 preceding siblings ...)
  2024-03-08 18:34 ` [PATCH setup 05/16] Don't call Antivirus::AtExit() directly from Logger::exit() Jon Turney
@ 2024-03-08 18:34 ` Jon Turney
  2024-03-08 18:34 ` [PATCH setup 07/16] Split out URL fetching progress reporting Jon Turney
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Jon Turney @ 2024-03-08 18:34 UTC (permalink / raw)
  To: cygwin-apps; +Cc: Jon Turney

Simplify how we check for a setup.rc settings file in the local cache
dir (Who knew that setup even did this?): pass the directory down to
UserSettings::open_settings() as a parameter, rather than by storing it
in an (otherwise unused) member.

Also: rename the 'cwd' parameter, because it's actually an arbitrary
directory, not the cwd.

(Archeology seems to indicate that at one stage we'd save settings in
the cwd if we needed to write them before the cygwin root was known, and
migrate that file to the cygwin root when it becomes known; then we
changed to keeping that file in the cache dir, then we forgot to migrate
it, so perhaps all this complexity isn't needed?)
---
 UserSettings.cc | 12 +++++++-----
 UserSettings.h  |  4 +---
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/UserSettings.cc b/UserSettings.cc
index c8ddd3d..3ec6798 100644
--- a/UserSettings.cc
+++ b/UserSettings.cc
@@ -65,14 +65,17 @@ UserSettings::extend_table (ssize_t i)
 }
 
 io_stream *
-UserSettings::open_settings (const char *filename, std::string &pathname)
+UserSettings::open_settings (const char *filename, std::string &dir, std::string &pathname)
 {
+  // first look for a settings file in specified dir
   pathname = "file://";
-  pathname += cwd;
-  if (!isdirsep (cwd[cwd.size () - 1]) && !isdirsep (filename[0]))
+  pathname += dir;
+  if (!isdirsep (dir[dir.size () - 1]) && !isdirsep (filename[0]))
     pathname += "/";
   pathname += filename;
   io_stream *f = io_stream::open(pathname, "rt", 0);
+
+  // if not found, look in cygwin installation
   if (!f)
     {
       pathname = "cygfile:///etc/setup/";
@@ -92,8 +95,7 @@ UserSettings::UserSettings ()
 void
 UserSettings::load (std::string local_dir)
 {
-  cwd = local_dir;
-  io_stream *f = open_settings ("setup.rc", filename);
+  io_stream *f = open_settings ("setup.rc", local_dir, filename);
 
   if (!f)
     return;
diff --git a/UserSettings.h b/UserSettings.h
index 3de06e1..dc06ab2 100644
--- a/UserSettings.h
+++ b/UserSettings.h
@@ -27,7 +27,6 @@ private:
   ssize_t table_len;
 
   std::string filename;
-  std::string cwd;
 
 public:
   static class UserSettings *global;
@@ -44,8 +43,7 @@ public:
 
 private:
   void extend_table (ssize_t);
-  io_stream *open_settings (const char *, std::string&);
-
+  io_stream *open_settings (const char *, std::string &, std::string&);
 };
 
 #endif // SETUP_USERSETTINGS_H
-- 
2.43.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH setup 07/16] Split out URL fetching progress reporting
  2024-03-08 18:34 [PATCH setup 00/16] Groundwork for a GUI-less installation tool Jon Turney
                   ` (5 preceding siblings ...)
  2024-03-08 18:34 ` [PATCH setup 06/16] Simplify invocation of UserSettings::open_settings() Jon Turney
@ 2024-03-08 18:34 ` Jon Turney
  2024-03-08 18:34 ` [PATCH setup 08/16] Instantiate found_ini_list in ini.cc Jon Turney
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Jon Turney @ 2024-03-08 18:34 UTC (permalink / raw)
  To: cygwin-apps; +Cc: Jon Turney

Rename IniParseFeedback.h to Feedback.h

Do URL fetching progress reporting via an interface defined by the
methods added to the interface defined by the virtual base class
Feedback, which can be implemented for GUI (via ThreeBar) or CLI feedback.

This is all a bit ad-hoc at the moment, based on the existing reporting
points, rather than a studied design.

Ultimately this Feedback class will grow to contain all the
download/hash/install/uninstall reporting.

Future work: The fact that we do extra key fetching inside the guts of
verify_ini_file_sig() (and so need to report progress from there) is
pretty disgusting.  We should probably fetch them up-front and hand them
down to there...
---
 Feedback.h                                    |  54 ++++++
 IniDBBuilderPackage.cc                        |   4 +-
 IniDBBuilderPackage.h                         |   6 +-
 IniParseFeedback.h                            |  38 ----
 Makefile.am                                   |   9 +-
 CliParseFeedback.h => cli/CliFeedback.h       |  31 +++-
 cli/CliGetUrlFeedback.cc                      |  91 ++++++++++
 .../CliParseFeedback.cc                       |  28 ++-
 crypto.cc                                     |  18 +-
 crypto.h                                      |   9 +-
 download.cc                                   |  17 +-
 fromcwd.cc                                    |   1 -
 geturl.cc                                     | 130 +++-----------
 geturl.h                                      |  13 +-
 gui/GuiFeedback.h                             |  64 +++++++
 gui/GuiGetUrlFeedback.cc                      | 119 +++++++++++++
 gui/GuiParseFeedback.cc                       | 164 ++++++++++--------
 gui/SitePage.cc                               |  19 +-
 ini.cc                                        |  36 ++--
 ini.h                                         |   7 +-
 inilex.ll                                     |   6 +-
 inilintmain.cc                                |  10 +-
 22 files changed, 572 insertions(+), 302 deletions(-)
 create mode 100644 Feedback.h
 delete mode 100644 IniParseFeedback.h
 rename CliParseFeedback.h => cli/CliFeedback.h (52%)
 create mode 100644 cli/CliGetUrlFeedback.cc
 rename CliParseFeedback.cc => cli/CliParseFeedback.cc (58%)
 create mode 100644 gui/GuiFeedback.h
 create mode 100644 gui/GuiGetUrlFeedback.cc

diff --git a/Feedback.h b/Feedback.h
new file mode 100644
index 0000000..8f603a6
--- /dev/null
+++ b/Feedback.h
@@ -0,0 +1,54 @@
+/*
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     A copy of the GNU General Public License can be found at
+ *     http://www.gnu.org/
+ *
+ */
+
+#ifndef SETUP_FEEDBACK_H
+#define SETUP_FEEDBACK_H
+
+#include "win32.h"
+#include <string>
+
+/* Interface for feedback from ini parsing and URL fetching.
+ *
+ * Used to send feedback that users need but that should not interrupt
+ * processing.
+ *
+ * Fatal errors are (may be) thrown as exceptions.
+ */
+
+class Feedback
+{
+public:
+  // IniParsing
+  virtual void parse_init () = 0;
+  virtual void parse_finish () = 0;
+  virtual void progress (unsigned long const, unsigned long const) = 0;
+  virtual void iniName (const std::string& ) = 0;
+  virtual void babble (const std::string& ) const = 0;
+  virtual void warning (const std::string& ) const = 0;
+  virtual void show_errors () const = 0;
+  virtual void note_error(int lineno, const std::string &error) = 0;
+  virtual bool has_errors () const = 0;
+
+  // URL fetching
+  virtual void fetch_progress_disable (bool) = 0;
+  virtual void fetch_init (const std::string &url, int length) = 0;
+  virtual void fetch_set_length(int length) = 0;
+  virtual void fetch_set_total_length(long long int total_length) = 0;
+  virtual void fetch_progress (int bytes) = 0;
+  virtual void fetch_total_progress () = 0;
+  virtual void fetch_finish (int total_bytes) = 0;
+  virtual void fetch_fatal (const char *filename, const char *err) = 0;
+
+  //
+  virtual HWND owner () = 0;
+};
+
+#endif /* SETUP_FEEDBACK_H */
diff --git a/IniDBBuilderPackage.cc b/IniDBBuilderPackage.cc
index 039404b..aa6dec7 100644
--- a/IniDBBuilderPackage.cc
+++ b/IniDBBuilderPackage.cc
@@ -19,7 +19,7 @@
 
 #include "setup_version.h"
 
-#include "IniParseFeedback.h"
+#include "Feedback.h"
 #include "package_db.h"
 #include "package_meta.h"
 #include "ini.h"
@@ -29,7 +29,7 @@
 #include "PackageSpecification.h"
 #include <algorithm>
 
-IniDBBuilderPackage::IniDBBuilderPackage (IniParseFeedback const &aFeedback) :
+IniDBBuilderPackage::IniDBBuilderPackage (Feedback const &aFeedback) :
   currentSpec (0), _feedback (aFeedback), minimum_version_checked(FALSE) {}
 
 IniDBBuilderPackage::~IniDBBuilderPackage()
diff --git a/IniDBBuilderPackage.h b/IniDBBuilderPackage.h
index 3e3a9e4..0f59257 100644
--- a/IniDBBuilderPackage.h
+++ b/IniDBBuilderPackage.h
@@ -24,13 +24,13 @@
 #include "String++.h"
 #include "libsolv.h"
 
-class IniParseFeedback;
+class Feedback;
 class packagesource;
 
 class IniDBBuilderPackage:public IniDBBuilder
 {
 public:
-  IniDBBuilderPackage (IniParseFeedback const &);
+  IniDBBuilderPackage (Feedback const &);
   ~IniDBBuilderPackage ();
 
   void buildTimestamp (const std::string& );
@@ -88,7 +88,7 @@ private:
   SolverPool::addPackageData cbpv;
   std::set <std::string> replace_versions;
 
-  IniParseFeedback const &_feedback;
+  Feedback const &_feedback;
   bool minimum_version_checked;
 };
 
diff --git a/IniParseFeedback.h b/IniParseFeedback.h
deleted file mode 100644
index c3c7803..0000000
--- a/IniParseFeedback.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2002 Robert Collins.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     A copy of the GNU General Public License can be found at
- *     http://www.gnu.org/
- *
- * Written by Robert Collins <robertc@hotmail.com>
- *
- */
-
-#ifndef SETUP_INIPARSEFEEDBACK_H
-#define SETUP_INIPARSEFEEDBACK_H
-
-
-#include <string>
-/* Strategy for feedback from IniParsing.
- * Used by the builder or parsing classes to send feedback that users need
- * but that should not interrupt parsing.
- * Fatal errors are thrown as exceptions.
- */
-class IniParseFeedback
-{
-public:
-  virtual void progress (unsigned long const, unsigned long const) = 0;
-  virtual void iniName (const std::string& ) = 0;
-  virtual void babble (const std::string& ) const = 0;
-  virtual void warning (const std::string& ) const = 0;
-  virtual void show_errors () const = 0;
-  virtual void note_error(int lineno, const std::string &error) = 0;
-  virtual bool has_errors () const = 0;
-};
-
-#endif /* SETUP_INIPARSEFEEDBACK_H */
diff --git a/Makefile.am b/Makefile.am
index f753961..de066b7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -65,8 +65,9 @@ inilint_LDADD = \
 inilint_SOURCES = \
 	filemanip.cc \
 	filemanip.h \
-	CliParseFeedback.cc \
-	CliParseFeedback.h \
+	cli/CliParseFeedback.cc \
+	cli/CliGetUrlFeedback.cc \
+	cli/CliFeedback.h \
 	LogSingleton.cc \
 	LogSingleton.h \
 	IniDBBuilder.h \
@@ -181,6 +182,8 @@ endif
 	gpg-packet.cc \
 	gpg-packet.h \
 	gui/GuiParseFeedback.cc \
+	gui/GuiGetUrlFeedback.cc \
+	gui/GuiFeedback.h \
 	ini.cc \
 	ini.h \
 	IniDBBuilder.h \
@@ -188,7 +191,7 @@ endif
 	IniDBBuilderPackage.h \
 	inilex.ll \
 	iniparse.yy \
-	IniParseFeedback.h \
+	Feedback.h \
 	install.cc \
 	io_stream.cc \
 	io_stream.h \
diff --git a/CliParseFeedback.h b/cli/CliFeedback.h
similarity index 52%
rename from CliParseFeedback.h
rename to cli/CliFeedback.h
index a19659e..3bcc23c 100644
--- a/CliParseFeedback.h
+++ b/cli/CliFeedback.h
@@ -11,11 +11,14 @@
  *
  */
 
-#include "IniParseFeedback.h"
+#include "Feedback.h"
 
-class CliParseFeedback : public IniParseFeedback
+class CliFeedback : public Feedback
 {
+  // ini parse
 public:
+  virtual void parse_init ();
+  virtual void parse_finish ();
   virtual void progress (unsigned long const pos, unsigned long const max);
   virtual void iniName (const std::string& name);
   virtual void babble (const std::string& message) const;
@@ -25,4 +28,28 @@ public:
   virtual bool has_errors () const;
 private:
   int error_count = 0;
+
+  // URL fetch
+public:
+  void fetch_progress_disable (bool);
+  void fetch_init (const std::string &url, int length);
+  void fetch_set_length(int length);
+  void fetch_set_total_length(long long int total_length);
+  void fetch_progress (int bytes);
+  void fetch_total_progress ();
+  void fetch_finish (int total_bytes);
+  void fetch_fatal (const char *filename, const char *err);
+
+private:
+  int max_bytes;
+  long long int total_download_bytes = 0; // meaning ???
+  long long int total_download_bytes_sofar = 0;
+
+  unsigned int last_tics;
+  unsigned int start_tics;
+
+  // owner
+public:
+  HWND owner () { return NULL; }
+
 };
diff --git a/cli/CliGetUrlFeedback.cc b/cli/CliGetUrlFeedback.cc
new file mode 100644
index 0000000..1256118
--- /dev/null
+++ b/cli/CliGetUrlFeedback.cc
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2024 Jon Turney
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     A copy of the GNU General Public License can be found at
+ *     http://www.gnu.org/
+ *
+ */
+
+#include "cli/CliFeedback.h"
+#include "msg.h"
+#include "resource.h"
+#include <stdio.h>
+
+void
+CliFeedback::fetch_progress_disable(bool disable)
+{
+}
+
+void
+CliFeedback::fetch_init (const std::string &url, int length)
+{
+  max_bytes = length;
+  printf("Fetching: %s\n", url.c_str());
+  start_tics = GetTickCount ();
+}
+
+void
+CliFeedback::fetch_set_length(int length)
+{
+  max_bytes = length;
+}
+
+void
+CliFeedback::fetch_set_total_length(long long int total_length)
+{
+  total_download_bytes = total_length;
+  total_download_bytes_sofar = 0;
+}
+
+void
+CliFeedback::fetch_progress (int bytes)
+{
+  DWORD tics = GetTickCount ();
+  if (tics == start_tics)       // to prevent division by zero
+    return;
+  if (tics < last_tics + 200)   // to prevent flickering updates
+    return;
+  last_tics = tics;
+
+  double kbps = ((double)bytes) / (double)(tics - start_tics);
+
+  if (max_bytes > 0)
+    {
+      int perc = (int)(100.0 * ((double)bytes) / (double)max_bytes);
+      printf ("%d %%  (%dk/%dk)  %03.1f kB/s",
+              perc, bytes / 1000, max_bytes / 1000, kbps);
+
+    }
+  else
+    printf("%d  %2.1f kB/s", bytes, kbps);
+
+  if (total_download_bytes > 0)
+    {
+      int total_perc = (int)(100.0 * ((double)total_download_bytes_sofar + bytes/
+                                      (double)total_download_bytes));
+      printf("%d %%", total_perc);
+    }
+  printf("\n");
+}
+
+void
+CliFeedback::fetch_total_progress ()
+{
+}
+
+void
+CliFeedback::fetch_finish (int total_bytes)
+{
+  total_download_bytes_sofar += total_bytes;
+}
+
+void
+CliFeedback::fetch_fatal (const char *filename, const char *err)
+{
+  ::fatal (NULL, IDS_ERR_OPEN_WRITE, filename, err);
+}
diff --git a/CliParseFeedback.cc b/cli/CliParseFeedback.cc
similarity index 58%
rename from CliParseFeedback.cc
rename to cli/CliParseFeedback.cc
index 6dc48ba..a58ee5a 100644
--- a/CliParseFeedback.cc
+++ b/cli/CliParseFeedback.cc
@@ -11,35 +11,45 @@
  *
  */
 
-#include "CliParseFeedback.h"
+#include "cli/CliFeedback.h"
 #include "LogSingleton.h"
 #include <sstream>
 #include <iostream>
 
-void CliParseFeedback::progress (unsigned long const pos, unsigned long const max)
+void
+CliFeedback::parse_init()
 {
-  std::cout << pos << "/" << max << std::endl;
 }
 
-void CliParseFeedback::iniName (const std::string& name)
+void
+CliFeedback::parse_finish()
 {
 }
 
-void CliParseFeedback::babble (const std::string& message) const
+void CliFeedback::progress (unsigned long const pos, unsigned long const max)
+{
+  std::cout << pos << "/" << max << "\r";
+}
+
+void CliFeedback::iniName (const std::string& name)
+{
+}
+
+void CliFeedback::babble (const std::string& message) const
 {
   Log (LOG_BABBLE) << message << endLog;
 }
 
-void CliParseFeedback::warning (const std::string& message) const
+void CliFeedback::warning (const std::string& message) const
 {
   std::cout << "Warning: " << message << std::endl;
 }
 
-void CliParseFeedback::show_errors () const
+void CliFeedback::show_errors () const
 {
 }
 
-void CliParseFeedback::note_error(int lineno, const std::string &s)
+void CliFeedback::note_error(int lineno, const std::string &s)
 {
   std::ostringstream buf;
   buf << "line " << lineno << ": ";
@@ -48,7 +58,7 @@ void CliParseFeedback::note_error(int lineno, const std::string &s)
   error_count++;
 }
 
-bool CliParseFeedback::has_errors () const
+bool CliFeedback::has_errors () const
 {
   return (error_count > 0);
 }
diff --git a/crypto.cc b/crypto.cc
index a837f8d..96c5e60 100644
--- a/crypto.cc
+++ b/crypto.cc
@@ -18,6 +18,7 @@
 #include <unistd.h>
 #include <vector>
 #include "io_stream.h"
+#include "win32.h"
 #include "crypto.h"
 #include "compress.h"
 #include "gcrypt.h"
@@ -29,6 +30,7 @@
 #include "KeysSetting.h"
 #include "gpg-packet.h"
 #include "geturl.h"
+#include "Feedback.h"
 
 #ifndef CRYPTODEBUGGING
 #define CRYPTODEBUGGING         (0)
@@ -649,7 +651,7 @@ gcrypt_log_adaptor(void *priv, int level, const char *fmt, va_list args)
 
 /*  Verify the signature on an ini file.  Takes care of all key-handling.  */
 bool
-verify_ini_file_sig (io_stream *ini_file, io_stream *ini_sig_file, HWND owner)
+verify_ini_file_sig (io_stream *ini_file, io_stream *ini_sig_file, Feedback &feedback)
 {
   /*  Data returned from packet walker.  */
   struct sig_data sigdat;
@@ -674,7 +676,7 @@ verify_ini_file_sig (io_stream *ini_file, io_stream *ini_sig_file, HWND owner)
       gcry_check_version (NULL);
 
       if ((rv = gcry_control (GCRYCTL_SELFTEST)) != GPG_ERR_NO_ERROR)
-        ERRKIND (owner, IDS_CRYPTO_ERROR, rv, "libgcrypt selftest failed");
+        ERRKIND (feedback.owner(), IDS_CRYPTO_ERROR, rv, "libgcrypt selftest failed");
 
 #if CRYPTODEBUGGING
       gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1);
@@ -687,7 +689,7 @@ verify_ini_file_sig (io_stream *ini_file, io_stream *ini_sig_file, HWND owner)
   rv = gcry_sexp_new (&cygwin_key, cygwin_pubkey_sexpr, strlen (cygwin_pubkey_sexpr), 1);
   if (rv != GPG_ERR_NO_ERROR)
     {
-      ERRKIND (owner, IDS_CRYPTO_ERROR, rv, "while creating pubkey s-expr.");
+      ERRKIND (feedback.owner(), IDS_CRYPTO_ERROR, rv, "while creating pubkey s-expr.");
     }
   else
     {
@@ -707,7 +709,7 @@ verify_ini_file_sig (io_stream *ini_file, io_stream *ini_sig_file, HWND owner)
       rv = gcry_sexp_new (&cygwin_old_key, cygwin_old_pubkey_sexpr, strlen (cygwin_old_pubkey_sexpr), 1);
       if (rv != GPG_ERR_NO_ERROR)
         {
-          ERRKIND (owner, IDS_CRYPTO_ERROR, rv, "while creating old pubkey s-expr.");
+          ERRKIND (feedback.owner(), IDS_CRYPTO_ERROR, rv, "while creating old pubkey s-expr.");
         }
       else
         {
@@ -791,7 +793,7 @@ verify_ini_file_sig (io_stream *ini_file, io_stream *ini_sig_file, HWND owner)
 	}
       else
 	{
-	  ERRKIND (owner, IDS_CRYPTO_ERROR, rv, "invalid command-line pubkey s-expr.");
+	  ERRKIND (feedback.owner(), IDS_CRYPTO_ERROR, rv, "invalid command-line pubkey s-expr.");
 	}
     }
 
@@ -801,11 +803,11 @@ verify_ini_file_sig (io_stream *ini_file, io_stream *ini_sig_file, HWND owner)
 					= ExtraKeysFiles.begin ();
 		it != ExtraKeysFiles.end (); ++it)
     {
-      io_stream *keys = get_url_to_membuf (*it, owner);
+      io_stream *keys = get_url_to_membuf (*it, feedback);
       if (keys)
 	{
 	  struct key_data kdat;
-	  pkt_walk_packets (keys, key_file_walker, owner, 0, keys->get_size (), &kdat);
+	  pkt_walk_packets (keys, key_file_walker, feedback.owner(), 0, keys->get_size (), &kdat);
 	  // We now have a vector of (some/any?) keys returned from
 	  // the walker; add them to the list to try.
 	  while (!kdat.keys.empty ())
@@ -835,7 +837,7 @@ verify_ini_file_sig (io_stream *ini_file, io_stream *ini_sig_file, HWND owner)
   sigdat.sign_data = ini_file;
   sigdat.keys_to_try = &keys_to_try;
 
-  pkt_walk_packets (ini_sig_file, sig_file_walker, owner, 0,
+  pkt_walk_packets (ini_sig_file, sig_file_walker, feedback.owner(), 0,
                     ini_sig_file->get_size (), &sigdat);
 
   sig_ok = sigdat.valid;
diff --git a/crypto.h b/crypto.h
index 661d86d..17389e4 100644
--- a/crypto.h
+++ b/crypto.h
@@ -17,20 +17,19 @@
 #define SETUP_CRYPTO_H
 
 /* This module uses libgcrypt functionality to verify signatures
- * on downloaded setup.ini or setup.bz2 files.
+ * on downloaded (compressed) setup.ini files.
  */
 
-/* for HWND */
-#include "win32.h" 
+class Feedback;
 class io_stream;
 
 /*  This is currently the only public API exported by the module; it
-  takes the contents of setup.ini or setup.bz2 in one (memory-based,
+  takes the contents of (compressed) setup.ini in one (memory-based,
   for preference) io_stream, and the contents of the related signature
   file in another.  It is called from ini.cc/do_remote_ini() and returns
   true if the signature verified OK; if it returns false, you MUST NOT
   use the failed ini file - doubly so if it's a compressed stream!  */
-extern bool verify_ini_file_sig (io_stream *ini_file, io_stream *ini_sig_file, HWND owner);
+bool verify_ini_file_sig (io_stream *ini_file, io_stream *ini_sig_file, Feedback &feedback);
 
 /*
 5.2.2.  Version 3 Signature Packet Format
diff --git a/download.cc b/download.cc
index 5bfcebf..02fd484 100644
--- a/download.cc
+++ b/download.cc
@@ -42,6 +42,7 @@
 #include "package_source.h"
 
 #include "threebar.h"
+#include "gui/GuiFeedback.h"
 
 #include "Exception.h"
 
@@ -146,11 +147,11 @@ check_for_cached (packagesource & pkgsource, HWND owner, bool mirror_mode,
 
 /* download a file from a mirror site to the local cache. */
 static int
-download_one (packagesource & pkgsource, HWND owner)
+download_one (packagesource & pkgsource, Feedback &feedback)
 {
   try
     {
-      if (check_for_cached (pkgsource, owner))
+      if (check_for_cached (pkgsource, feedback.owner()))
         return 0;
     }
   catch (Exception * e)
@@ -158,7 +159,7 @@ download_one (packagesource & pkgsource, HWND owner)
       // We know what to do with these..
       if (e->errNo() == APPERR_CORRUPT_PACKAGE)
 	{
-	  fatal (owner, IDS_CORRUPT_PACKAGE, pkgsource.Canonical());
+	  fatal (feedback.owner(), IDS_CORRUPT_PACKAGE, pkgsource.Canonical());
     	  return 1;
 	}
       // Unexpected exception.
@@ -176,7 +177,7 @@ download_one (packagesource & pkgsource, HWND owner)
       io_stream::mkpath_p (PATH_TO_FILE, "file://" + local, 0);
 
       if (get_url_to_file(n->key + pkgsource.Canonical (),
-			  local + ".tmp", pkgsource.size, owner))
+			  local + ".tmp", pkgsource.size, feedback))
 	{
 	  /* FIXME: note new source ? */
 	  continue;
@@ -274,8 +275,6 @@ static int
 do_download_thread (HINSTANCE h, HWND owner)
 {
   int errors = 0;
-  total_download_bytes = 0;
-  total_download_bytes_sofar = 0;
   download_failures.clear ();
 
   Progress.SetText1 (IDS_PROGRESS_CHECKING);
@@ -286,6 +285,7 @@ do_download_thread (HINSTANCE h, HWND owner)
   const SolverTransactionList &t = db.solution.transactions();
 
   /* calculate the total size of the download */
+  long long int total_download_bytes = 0;
   for (SolverTransactionList::const_iterator i = t.begin (); i != t.end (); ++i)
     {
       if (i->type != SolverTransaction::transInstall)
@@ -308,6 +308,9 @@ do_download_thread (HINSTANCE h, HWND owner)
       Progress.SetBar2(std::distance(t.begin(), i) + 1, t.size());
     }
 
+  GuiFeedback feedback(owner);
+  feedback.fetch_set_total_length(total_download_bytes);
+
   /* and do the download. FIXME: This here we assign a new name for the cached version
    * and check that above.
    */
@@ -319,7 +322,7 @@ do_download_thread (HINSTANCE h, HWND owner)
 
 	{
 	  int e = 0;
-          e += download_one (*version.source(), owner);
+          e += download_one (*version.source(), feedback);
 	  errors += e;
 	  if (e)
 	    download_failures.push_back (version);
diff --git a/fromcwd.cc b/fromcwd.cc
index 3e77ad3..f58e955 100644
--- a/fromcwd.cc
+++ b/fromcwd.cc
@@ -32,7 +32,6 @@
 
 #include "FindVisitor.h"
 #include "IniDBBuilderPackage.h"
-#include "IniParseFeedback.h"
 
 class SetupFindVisitor : public FindVisitor
 {
diff --git a/geturl.cc b/geturl.cc
index 679e468..c4187a6 100644
--- a/geturl.cc
+++ b/geturl.cc
@@ -15,12 +15,10 @@
  *
  */
 
-/* The purpose of this file is to act as a pretty interface to
-   netio.cc.  We add a progress dialog and some convenience functions
-   (like collect to string or file */
+/* The purpose of this file is to act as a pretty interface to netio.cc.  We add
+   a progress reporting and some convenience functions (like collect to string
+   or file) */
 
-#include "win32.h"
-#include "commctrl.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -30,87 +28,24 @@
 #include "geturl.h"
 #include "resource.h"
 #include "netio.h"
-#include "msg.h"
 #include "io_stream.h"
 #include "io_stream_memory.h"
 #include "state.h"
-#include "diskfull.h"
-#include "mount.h"
 #include "filemanip.h"
-
-#include "threebar.h"
+#include "String++.h"
 
 #include "Exception.h"
 
 #include "LogSingleton.h"
-
-extern ThreeBarProgressPage Progress;
-
-static int max_bytes = 0;
-static int is_local_install = 0;
-
-long long int total_download_bytes = 0;
-long long int total_download_bytes_sofar = 0;
-
-static DWORD start_tics;
+#include "Feedback.h"
 
 static void
-init_dialog (const std::string &url, int length)
+getUrlToStream (const std::string &_url, io_stream *output, Feedback &feedback)
 {
-  if (is_local_install)
-    return;
-
-  std::string::size_type divide = url.find_last_of('/');
-  max_bytes = length;
-  Progress.SetText1(IDS_PROGRESS_DOWNLOADING);
-  std::wstring fmt = LoadStringW(IDS_PROGRESS_DOWNLOADING_FROM);
-  std::wstring s = format(fmt,
-                          url.substr(divide + 1).c_str(),
-                          url.substr(0, divide).c_str());
-  Progress.SetText2(s.c_str());
-  Progress.SetText3(IDS_PROGRESS_CONNECTING);
-  Progress.SetBar1(0);
-  start_tics = GetTickCount ();
-}
+  // we turn off this feedback for local files
+  feedback.fetch_progress_disable((source == IDC_SOURCE_LOCALDIR));
 
-
-static void
-progress (int bytes)
-{
-  if (is_local_install)
-    return;
-  static char buf[100];
-  double kbps;
-  static unsigned int last_tics = 0;
-  DWORD tics = GetTickCount ();
-  if (tics == start_tics)	// to prevent division by zero
-    return;
-  if (tics < last_tics + 200)	// to prevent flickering updates
-    return;
-  last_tics = tics;
-
-  kbps = ((double)bytes) / (double)(tics - start_tics);
-  if (max_bytes > 0)
-    {
-      int perc = (int)(100.0 * ((double)bytes) / (double)max_bytes);
-      Progress.SetBar1(bytes, max_bytes);
-      sprintf (buf, "%d %%  (%dk/%dk)  %03.1f kB/s",
-	       perc, bytes / 1000, max_bytes / 1000, kbps);
-      if (total_download_bytes > 0)
-     	  Progress.SetBar2(total_download_bytes_sofar + bytes,
-			   total_download_bytes);
-    }
-  else
-    sprintf (buf, "%d  %2.1f kB/s", bytes, kbps);
-
-  Progress.SetText3(buf);
-}
-
-static void
-getUrlToStream (const std::string &_url, io_stream *output)
-{
-  is_local_install = (source == IDC_SOURCE_LOCALDIR);
-  init_dialog (_url, 0);
+  feedback.fetch_init (_url, 0);
   NetIO *n = NetIO::open (_url.c_str(), true);
   if (!n || !n->ok ())
     {
@@ -119,10 +54,10 @@ getUrlToStream (const std::string &_url, io_stream *output)
     }
 
   if (n->file_size)
-    max_bytes = n->file_size;
+    feedback.fetch_set_length(n->file_size);
 
   int total_bytes = 0;
-  progress (0);
+  feedback.fetch_progress (0);
   while (1)
     {
       char buf[2048];
@@ -135,7 +70,7 @@ getUrlToStream (const std::string &_url, io_stream *output)
 	    /* FIXME: Show an error message */
 	    break;
 	  total_bytes += rlen;
-	  progress (total_bytes);
+	  feedback.fetch_progress (total_bytes);
 	}
       else
 	break;
@@ -148,13 +83,13 @@ getUrlToStream (const std::string &_url, io_stream *output)
 }
 
 io_stream *
-get_url_to_membuf (const std::string &_url, HWND owner)
+get_url_to_membuf (const std::string &_url, Feedback &feedback)
 {
   io_stream_memory *membuf = new io_stream_memory ();
-  try 
+  try
     {
-      getUrlToStream (_url, membuf);
-      
+      getUrlToStream (_url, membuf, feedback);
+
       if (membuf->seek (0, IO_SEEK_SET))
     	{
     	  if (membuf)
@@ -175,9 +110,9 @@ get_url_to_membuf (const std::string &_url, HWND owner)
 
 // predicate: url has no '\0''s in it.
 std::string
-get_url_to_string (const std::string &_url, HWND owner)
+get_url_to_string (const std::string &_url, Feedback &feedback)
 {
-  io_stream *stream = get_url_to_membuf (_url, owner);
+  io_stream *stream = get_url_to_membuf (_url, feedback);
   if (!stream)
     return std::string();
   size_t bytes = stream->get_size ();
@@ -200,15 +135,11 @@ int
 get_url_to_file (const std::string &_url,
                  const std::string &_filename,
                  int expected_length,
-		 HWND owner)
+                 Feedback &feedback)
 {
   Log (LOG_BABBLE) << "get_url_to_file " << _url << " " << _filename << endLog;
-  if (total_download_bytes > 0)
-    {
-      int df = diskfull (get_root_dir ().c_str());
-      Progress.SetBar3(df);
-    }
-  init_dialog (_url, expected_length);
+  feedback.fetch_total_progress();
+  feedback.fetch_init(_url, expected_length);
 
   remove (_filename.c_str());		/* but ignore errors */
 
@@ -225,14 +156,14 @@ get_url_to_file (const std::string &_url,
       const char *err = strerror (errno);
       if (!err)
 	err = "(unknown error)";
-      fatal (owner, IDS_ERR_OPEN_WRITE, _filename.c_str(), err);
+      feedback.fetch_fatal (_filename.c_str(), err);
     }
 
   if (n->file_size)
-    max_bytes = n->file_size;
+    feedback.fetch_set_length(n->file_size);
 
   int total_bytes = 0;
-  progress (0);
+  feedback.fetch_progress(0);
   while (1)
     {
       char buf[8192];
@@ -242,22 +173,15 @@ get_url_to_file (const std::string &_url,
 	break;
       fwrite (buf, 1, count, f);
       total_bytes += count;
-      progress (total_bytes);
+      feedback.fetch_progress (total_bytes);
     }
 
-  total_download_bytes_sofar += total_bytes;
-
   fclose (f);
   if (n)
     delete n;
 
-  if (total_download_bytes > 0)
-    {
-      int df = diskfull (get_root_dir ().c_str());
-	  Progress.SetBar3(df);
-    }
-  Progress.SetText3("");
+  feedback.fetch_total_progress();
+  feedback.fetch_finish(total_bytes);
 
   return 0;
 }
-
diff --git a/geturl.h b/geturl.h
index f4e963e..d917543 100644
--- a/geturl.h
+++ b/geturl.h
@@ -16,19 +16,16 @@
 #ifndef SETUP_GETURL_H
 #define SETUP_GETURL_H
 
-/* Download files from the Internet.  These pop up a progress dialog;
-   don't forget to dismiss it when you're done downloading for a while */
+/* Download files from the Internet. */
 
 #include <string>
 
-extern long long int total_download_bytes;
-extern long long int total_download_bytes_sofar;
-
 class io_stream;
+class Feedback;
 
-io_stream *get_url_to_membuf (const std::string &_url, HWND owner);
-std::string get_url_to_string (const std::string &_url, HWND owner);
+io_stream *get_url_to_membuf (const std::string &_url, Feedback &feedback);
+std::string get_url_to_string (const std::string &_url, Feedback &feedback);
 int get_url_to_file (const std::string &_url, const std::string &_filename,
-                     int expected_size, HWND owner);
+                     int expected_size, Feedback &feedback);
 
 #endif /* SETUP_GETURL_H */
diff --git a/gui/GuiFeedback.h b/gui/GuiFeedback.h
new file mode 100644
index 0000000..1dcd42f
--- /dev/null
+++ b/gui/GuiFeedback.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2024 Jon Turney
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     A copy of the GNU General Public License can be found at
+ *     http://www.gnu.org/
+ *
+ */
+
+#include "Feedback.h"
+
+class GuiFeedback : public Feedback
+{
+  // constructor
+public:
+  GuiFeedback(HWND hwnd) : owner_window(hwnd) { };
+
+  // ini parse
+public:
+  void parse_init ();
+  void parse_finish ();
+  void progress (unsigned long const, unsigned long const);
+  void iniName (const std::string& );
+  void babble (const std::string& ) const;
+  void warning (const std::string& ) const;
+  void show_errors () const;
+  void note_error(int lineno, const std::string &error);
+  bool has_errors () const;
+
+private:
+  unsigned int lastpct;
+  std::string filename;
+  std::string yyerror_messages;
+  int yyerror_count;
+
+  // URL fetch
+public:
+  void fetch_progress_disable (bool);
+  void fetch_init (const std::string &url, int length);
+  void fetch_set_length(int length);
+  void fetch_set_total_length(long long int total_length);
+  void fetch_progress (int bytes);
+  void fetch_total_progress ();
+  void fetch_finish (int total_bytes);
+  void fetch_fatal (const char *filename, const char *err);
+
+private:
+  int is_local_install = 0;
+  int max_bytes = 0;
+  long long int total_download_bytes = 0;
+  long long int total_download_bytes_sofar = 0;
+  DWORD start_tics;
+
+public:
+  // owner
+  HWND owner () { return owner_window; }
+
+private:
+  HWND owner_window;
+};
diff --git a/gui/GuiGetUrlFeedback.cc b/gui/GuiGetUrlFeedback.cc
new file mode 100644
index 0000000..1b5ce9a
--- /dev/null
+++ b/gui/GuiGetUrlFeedback.cc
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2024 Jon Turney
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     A copy of the GNU General Public License can be found at
+ *     http://www.gnu.org/
+ *
+ */
+
+#include "win32.h"
+#include "commctrl.h"
+#include "resource.h"
+#include "diskfull.h"
+#include "mount.h"
+#include "threebar.h"
+#include "msg.h"
+#include "String++.h"
+
+#include "gui/GuiFeedback.h"
+
+extern ThreeBarProgressPage Progress;
+
+void
+GuiFeedback::fetch_set_total_length(long long int total_length)
+{
+  total_download_bytes = total_length;
+  total_download_bytes_sofar = 0;
+}
+
+void
+GuiFeedback::fetch_progress_disable(bool disable)
+{
+  is_local_install = disable;
+}
+
+void
+GuiFeedback::fetch_init (const std::string &url, int length)
+{
+  if (is_local_install)
+    return;
+
+  std::string::size_type divide = url.find_last_of('/');
+  max_bytes = length;
+  Progress.SetText1(IDS_PROGRESS_DOWNLOADING);
+  std::wstring fmt = LoadStringW(IDS_PROGRESS_DOWNLOADING_FROM);
+  std::wstring s = format(fmt,
+                          url.substr(divide + 1).c_str(),
+                          url.substr(0, divide).c_str());
+  Progress.SetText2(s.c_str());
+  Progress.SetText3(IDS_PROGRESS_CONNECTING);
+  Progress.SetBar1(0);
+  start_tics = GetTickCount ();
+}
+
+void
+GuiFeedback::fetch_set_length(int length)
+{
+  max_bytes = length;
+}
+
+void
+GuiFeedback::fetch_progress (int bytes)
+{
+  if (is_local_install)
+    return;
+
+  static char buf[100];
+  double kbps;
+  static unsigned int last_tics = 0;
+  DWORD tics = GetTickCount ();
+  if (tics == start_tics)       // to prevent division by zero
+    return;
+  if (tics < last_tics + 200)   // to prevent flickering updates
+    return;
+  last_tics = tics;
+
+  kbps = ((double)bytes) / (double)(tics - start_tics);
+  if (max_bytes > 0)
+    {
+      int perc = (int)(100.0 * ((double)bytes) / (double)max_bytes);
+      Progress.SetBar1(bytes, max_bytes);
+      sprintf (buf, "%d %%  (%dk/%dk)  %03.1f kB/s",
+               perc, bytes / 1000, max_bytes / 1000, kbps);
+      if (total_download_bytes > 0)
+          Progress.SetBar2(total_download_bytes_sofar + bytes,
+                           total_download_bytes);
+    }
+  else
+    sprintf (buf, "%d  %2.1f kB/s", bytes, kbps);
+
+  Progress.SetText3(buf);
+}
+
+void
+GuiFeedback::fetch_total_progress ()
+{
+  if (total_download_bytes > 0)
+    {
+      int df = diskfull (get_root_dir ().c_str());
+      Progress.SetBar3(df);
+    }
+}
+
+void
+GuiFeedback::fetch_finish (int total_bytes)
+{
+  total_download_bytes_sofar += total_bytes;
+  Progress.SetText3("");
+}
+
+void
+GuiFeedback::fetch_fatal (const char *filename, const char *err)
+{
+  ::fatal (owner_window, IDS_ERR_OPEN_WRITE, filename, err);
+}
diff --git a/gui/GuiParseFeedback.cc b/gui/GuiParseFeedback.cc
index 263fae1..6a2b7bc 100644
--- a/gui/GuiParseFeedback.cc
+++ b/gui/GuiParseFeedback.cc
@@ -14,7 +14,8 @@
  */
 
 #include "Exception.h"
-#include "IniParseFeedback.h"
+#include "gui/GuiFeedback.h"
+
 #include "ini.h"
 #include "msg.h"
 #include "resource.h"
@@ -23,87 +24,96 @@
 
 extern ThreeBarProgressPage Progress;
 
-class GuiParseFeedback : public IniParseFeedback
+void
+GuiFeedback::parse_init ()
 {
-public:
-  GuiParseFeedback () : lastpct (0)
-    {
-      Progress.SetText1 (IDS_PROGRESS_PARSING);
-      Progress.SetText2 ("");
-      Progress.SetText3 ("");
-      Progress.SetText4 (IDS_PROGRESS_PROGRESS);
+  Progress.SetText1 (IDS_PROGRESS_PARSING);
+  Progress.SetText2 ("");
+  Progress.SetText3 ("");
+  Progress.SetText4 (IDS_PROGRESS_PROGRESS);
+
+  lastpct = 0;
+  yyerror_count = 0;
+  yyerror_messages.clear ();
+}
 
-      yyerror_count = 0;
-      yyerror_messages.clear ();
-    }
-  virtual void progress (unsigned long const pos, unsigned long const max)
-    {
-      if (!max)
-        /* length not known or eof */
-        return;
-      if (lastpct == 100)
-        /* rounding down should mean this only ever fires once */
-        lastpct = 0;
-      if (pos * 100 / max > lastpct)
-        {
-          lastpct = pos * 100 / max;
-          /* Log (LOG_BABBLE) << lastpct << "% (" << pos << " of " << max
-            << " bytes of ini file read)" << endLog; */
-        }
-      Progress.SetBar1 (pos, max);
-
-      static char buf[100];
-      sprintf (buf, "%d %%  (%ldk/%ldk)", lastpct, pos/1000, max/1000);
-      Progress.SetText3 (buf);
-    }
-  virtual void iniName (const std::string& name)
-    {
-      Progress.SetText2 (name.c_str ());
-      Progress.SetText3 ("");
-      filename = name;
-    }
-  virtual void babble (const std::string& message)const
-    {
-      Log (LOG_BABBLE) << message << endLog;
-    }
-  virtual void warning (const std::string& message)const
+void
+GuiFeedback::parse_finish ()
+{
+  Progress.SetText2 ("");
+  Progress.SetText3 ("");
+  Progress.SetText4 (IDS_PROGRESS_PACKAGE);
+  Progress.SetBar1 (0);
+}
+
+void
+GuiFeedback::progress (unsigned long const pos, unsigned long const max)
+{
+  if (!max)
+    /* length not known or eof */
+    return;
+  if (lastpct == 100)
+    /* rounding down should mean this only ever fires once */
+    lastpct = 0;
+  if (pos * 100 / max > lastpct)
     {
-      mbox (Progress.GetHWND(), message.c_str (), "Warning", 0);
+      lastpct = pos * 100 / max;
+      /* Log (LOG_BABBLE) << lastpct << "% (" << pos << " of " << max
+         << " bytes of ini file read)" << endLog; */
     }
-  virtual void note_error(int lineno, const std::string &error)
-    {
-      char tmp[16];
-      sprintf (tmp, "%d", lineno);
+  Progress.SetBar1 (pos, max);
 
-      std::string e = filename + " line " + tmp + ": " + error;
+  static char buf[100];
+  sprintf (buf, "%d %%  (%ldk/%ldk)", lastpct, pos/1000, max/1000);
+  Progress.SetText3 (buf);
+}
 
-      if (!yyerror_messages.empty ())
-        yyerror_messages += "\n";
+void
+GuiFeedback::iniName (const std::string& name)
+{
+  Progress.SetText2 (name.c_str ());
+  Progress.SetText3 ("");
+  filename = name;
+}
 
-      yyerror_messages += e;
-      yyerror_count++;
-    }
-  virtual bool has_errors () const
-    {
-      return (yyerror_count > 0);
-    }
-  virtual void show_errors () const
-    {
-      mbox (Progress.GetHWND(), yyerror_messages.c_str (), "Parse Errors", 0);
-    }
-  virtual ~ GuiParseFeedback ()
-    {
-      Progress.SetText2 ("");
-      Progress.SetText3 ("");
-      Progress.SetText4 (IDS_PROGRESS_PACKAGE);
-      Progress.SetBar1 (0);
-    }
-private:
-  unsigned int lastpct;
-  std::string filename;
-  std::string yyerror_messages;
-  int yyerror_count;
-};
+void
+GuiFeedback::babble (const std::string& message)const
+{
+  Log (LOG_BABBLE) << message << endLog;
+}
+
+void
+GuiFeedback::warning (const std::string& message)const
+{
+  mbox (Progress.GetHWND(), message.c_str (), "Warning", 0);
+}
+
+void
+GuiFeedback::note_error(int lineno, const std::string &error)
+{
+  char tmp[16];
+  sprintf (tmp, "%d", lineno);
+
+  std::string e = filename + " line " + tmp + ": " + error;
+
+  if (!yyerror_messages.empty ())
+    yyerror_messages += "\n";
+
+  yyerror_messages += e;
+  yyerror_count++;
+}
+
+bool
+GuiFeedback::has_errors () const
+{
+  return (yyerror_count > 0);
+}
+
+void
+GuiFeedback::show_errors () const
+{
+  mbox (Progress.GetHWND(), yyerror_messages.c_str (), "Parse Errors", 0);
+}
 
 static DWORD WINAPI
 do_ini_thread_reflector (void* p)
@@ -115,8 +125,8 @@ do_ini_thread_reflector (void* p)
 
   try
   {
-    GuiParseFeedback feedback;
-    bool succeeded = do_ini_thread ((HINSTANCE)context[0], (HWND)context[1], feedback);
+    GuiFeedback feedback((HWND)context[1]);
+    bool succeeded = do_ini_thread(feedback);
 
     // Tell the progress page that we're done downloading
     Progress.PostMessageNow (WM_APP_SETUP_INI_DOWNLOAD_COMPLETE, 0, succeeded);
diff --git a/gui/SitePage.cc b/gui/SitePage.cc
index 69bac1d..1cdb1bf 100644
--- a/gui/SitePage.cc
+++ b/gui/SitePage.cc
@@ -39,6 +39,7 @@
 #include "ControlAdjuster.h"
 #include "Exception.h"
 #include "String++.h"
+#include "gui/GuiFeedback.h"
 
 #define MIRROR_LIST_URL "https://cygwin.com/mirrors.lst"
 
@@ -200,7 +201,7 @@ migrate_selected_site_list()
 }
 
 static int
-get_site_list (HINSTANCE h, HWND owner)
+get_site_list (Feedback &feedback)
 {
   char *theMirrorString, *theCachedString;
 
@@ -220,7 +221,7 @@ get_site_list (HINSTANCE h, HWND owner)
       cached_mirrors = "";
     }
 
-  std::string mirrors = OnlySiteOption ? std::string ("") : get_url_to_string (MIRROR_LIST_URL, owner);
+  std::string mirrors = OnlySiteOption ? std::string ("") : get_url_to_string (MIRROR_LIST_URL, feedback);
   if (mirrors.size())
     cache_needs_writing = true;
   else
@@ -228,7 +229,7 @@ get_site_list (HINSTANCE h, HWND owner)
       if (!cached_mirrors[0])
         {
           if (!OnlySiteOption)
-            note(owner, IDS_NO_MIRROR_LST);
+            note(feedback.owner(), IDS_NO_MIRROR_LST);
           Log (LOG_BABBLE) << "Defaulting to empty mirror list" << endLog;
         }
       else
@@ -257,27 +258,25 @@ static DWORD WINAPI
 do_download_site_info_thread (void *p)
 {
   HANDLE *context;
-  HINSTANCE hinst;
-  HWND h;
   context = (HANDLE *) p;
 
   SetThreadUILanguage(langid);
 
   try
   {
-    hinst = (HINSTANCE) (context[0]);
-    h = (HWND) (context[1]);
+    GuiFeedback feedback((HWND)(context[1]));
+
     static bool downloaded = false;
-    if (!downloaded && get_site_list (hinst, h))
+    if (!downloaded && get_site_list(feedback))
     {
       // Error: Couldn't download the site info.
       // Go back to the Net setup page.
-      mbox (h, IDS_GET_SITELIST_ERROR, MB_OK);
+      mbox (feedback.owner(), IDS_GET_SITELIST_ERROR, MB_OK);
 
       // Tell the progress page that we're done downloading
       Progress.PostMessageNow (WM_APP_SITE_INFO_DOWNLOAD_COMPLETE, 0, IDD_NET);
     }
-    else 
+    else
     {
       downloaded = true;
       // Everything worked, go to the site select page
diff --git a/ini.cc b/ini.cc
index 3d3cbde..09dda13 100644
--- a/ini.cc
+++ b/ini.cc
@@ -38,7 +38,7 @@
 #include "mount.h"
 #include "SiteSetting.h"
 #include "find.h"
-#include "IniParseFeedback.h"
+#include "Feedback.h"
 
 #include "io_stream.h"
 #include "io_stream_memory.h"
@@ -111,7 +111,7 @@ decompress_ini (io_stream *ini_file, std::string &current_ini_name)
 
 static io_stream*
 check_ini_sig (io_stream* ini_file, io_stream* ini_sig_file,
-	       bool& sig_fail, const char* site, const char* sig_name, HWND owner)
+	       bool& sig_fail, const char* site, const char* sig_name, Feedback &feedback)
 {
   /* Unless the NoVerifyOption is set, check the signature for the
      current setup and record the result.  On a failed signature check
@@ -125,15 +125,15 @@ check_ini_sig (io_stream* ini_file, io_stream* ini_sig_file,
 	// TODO: download the ini + signature file instead
 	if (casecompare (site, "localdir"))
 	  {
-	    note (owner, IDS_SETUPINI_MISSING, sig_name, site);
+	    note (feedback.owner(), IDS_SETUPINI_MISSING, sig_name, site);
 	    delete ini_file;
 	    ini_file = NULL;
 	    sig_fail = true;
 	  }
       }
-      else if (!verify_ini_file_sig (ini_file, ini_sig_file, owner))
+      else if (!verify_ini_file_sig (ini_file, ini_sig_file, feedback))
 	{
-	  note (owner, IDS_SIG_INVALID, sig_name, site);
+	  note (feedback.owner(), IDS_SIG_INVALID, sig_name, site);
 	  delete ini_sig_file;
 	  ini_sig_file = NULL;
 	  delete ini_file;
@@ -145,7 +145,7 @@ check_ini_sig (io_stream* ini_file, io_stream* ini_sig_file,
 }
 
 static bool
-do_local_ini (HWND owner, IniParseFeedback &myFeedback)
+do_local_ini (Feedback &myFeedback)
 {
   bool ini_error = false;
   io_stream *ini_file, *ini_sig_file;
@@ -163,13 +163,13 @@ do_local_ini (HWND owner, IniParseFeedback &myFeedback)
       ini_sig_file = io_stream::open ("file://" + current_ini_sig_name, "rb", 0);
       ini_file = io_stream::open ("file://" + current_ini_name, "rb", 0);
       ini_file = check_ini_sig (ini_file, ini_sig_file, sig_fail,
-				"localdir", current_ini_sig_name.c_str (), owner);
+				"localdir", current_ini_sig_name.c_str (), myFeedback);
       if (ini_file)
 	ini_file = decompress_ini (ini_file, current_ini_name);
       if (!ini_file || sig_fail)
 	{
 	  // no setup found or signature invalid
-	  note (owner, IDS_SETUPINI_MISSING, SetupBaseName.c_str (),
+	  note (myFeedback.owner(), IDS_SETUPINI_MISSING, SetupBaseName.c_str (),
 		"localdir");
 	  ini_error = true;
 	}
@@ -203,7 +203,7 @@ do_local_ini (HWND owner, IniParseFeedback &myFeedback)
 }
 
 static bool
-do_remote_ini (HWND owner, IniParseFeedback &myFeedback)
+do_remote_ini (Feedback &myFeedback)
 {
   bool ini_error = false;
   io_stream *ini_file = NULL, *ini_sig_file;
@@ -226,10 +226,10 @@ do_remote_ini (HWND owner, IniParseFeedback &myFeedback)
 	  current_ini_ext = *ext;
 	  current_ini_name = n->url + SetupIniDir + SetupBaseName + "." + current_ini_ext;
 	  current_ini_sig_name = current_ini_name + ".sig";
-	  ini_sig_file = get_url_to_membuf (current_ini_sig_name, owner);
-	  ini_file = get_url_to_membuf (current_ini_name, owner);
+	  ini_sig_file = get_url_to_membuf (current_ini_sig_name, myFeedback);
+	  ini_file = get_url_to_membuf (current_ini_name, myFeedback);
 	  ini_file = check_ini_sig (ini_file, ini_sig_file, sig_fail,
-				    n->url.c_str (), current_ini_sig_name.c_str (), owner);
+				    n->url.c_str (), current_ini_sig_name.c_str (), myFeedback);
 	  // stop searching as soon as we find a setup file
 	  if (ini_file)
 	    break;
@@ -239,7 +239,7 @@ do_remote_ini (HWND owner, IniParseFeedback &myFeedback)
       if (!ini_file || sig_fail)
 	{
 	  // no setup found or signature invalid
-	  note (owner, IDS_SETUPINI_MISSING, SetupBaseName.c_str (), n->url.c_str ());
+	  note (myFeedback.owner(), IDS_SETUPINI_MISSING, SetupBaseName.c_str (), n->url.c_str ());
 	  ini_error = true;
 	}
       else
@@ -282,7 +282,7 @@ do_remote_ini (HWND owner, IniParseFeedback &myFeedback)
 }
 
 bool
-do_ini_thread (HINSTANCE h, HWND owner, IniParseFeedback &feedback)
+do_ini_thread (Feedback &feedback)
 {
   packagedb db;
   db.init();
@@ -290,9 +290,9 @@ do_ini_thread (HINSTANCE h, HWND owner, IniParseFeedback &feedback)
   bool ini_error = true;
 
   if (source == IDC_SOURCE_LOCALDIR)
-    ini_error = do_local_ini (owner, feedback);
+    ini_error = do_local_ini (feedback);
   else
-    ini_error = do_remote_ini (owner, feedback);
+    ini_error = do_remote_ini (feedback);
 
   if (ini_error)
     return false;
@@ -314,7 +314,7 @@ do_ini_thread (HINSTANCE h, HWND owner, IniParseFeedback &feedback)
 	  if (old_timestamp && setup_timestamp
 	      && (old_timestamp > setup_timestamp))
 	    {
-	      int yn = yesno (owner, IDS_OLD_SETUPINI);
+	      int yn = yesno (feedback.owner(), IDS_OLD_SETUPINI);
 	      if (yn == IDNO)
 		Logger ().exit (1);
 	    }
@@ -340,7 +340,7 @@ do_ini_thread (HINSTANCE h, HWND owner, IniParseFeedback &feedback)
     {
       if ((version_compare (setup_version, ini_setup_version) < 0)
           && !NoVersionCheckOption)
-	note (owner, IDS_OLD_SETUP_VERSION, setup_version,
+	note (feedback.owner(), IDS_OLD_SETUP_VERSION, setup_version,
 	      ini_setup_version.c_str ());
     }
 
diff --git a/ini.h b/ini.h
index 6b24211..f1788e2 100644
--- a/ini.h
+++ b/ini.h
@@ -31,9 +31,10 @@ extern std::string SetupBaseName;
 
 class io_stream;
 class IniDBBuilder;
-class IniParseFeedback;
-void ini_init (io_stream *, IniDBBuilder *, IniParseFeedback &);
-bool do_ini_thread (HINSTANCE h, HWND owner, IniParseFeedback &feedback);
+class Feedback;
+
+void ini_init (io_stream *, IniDBBuilder *, Feedback &);
+bool do_ini_thread (Feedback &feedback);
 
 #define YYSTYPE char *
 
diff --git a/inilex.ll b/inilex.ll
index e25abf2..8ee9293 100644
--- a/inilex.ll
+++ b/inilex.ll
@@ -25,7 +25,7 @@
 #include "ini.h"
 #include "iniparse.hh"
 #include "String++.h"
-#include "IniParseFeedback.h"
+#include "Feedback.h"
 #include "sha2.h"
 
 #define YY_READ_BUF_SIZE 65536
@@ -167,10 +167,10 @@ B64	[a-zA-Z0-9_-]
 
 static io_stream *input_stream = 0;
 extern IniDBBuilder *iniBuilder;
-static IniParseFeedback *iniFeedback;
+static Feedback *iniFeedback;
 
 void
-ini_init(io_stream *stream, IniDBBuilder *aBuilder, IniParseFeedback &aFeedback)
+ini_init(io_stream *stream, IniDBBuilder *aBuilder, Feedback &aFeedback)
 {
   input_stream = stream;
   iniBuilder = aBuilder;
diff --git a/inilintmain.cc b/inilintmain.cc
index 886c152..9b3b0b3 100644
--- a/inilintmain.cc
+++ b/inilintmain.cc
@@ -15,7 +15,7 @@
 
 #include "io_stream.h"
 #include "IniDBBuilderLint.h"
-#include "CliParseFeedback.h"
+#include "cli/CliFeedback.h"
 #include "ini.h"
 #include <iostream>
 #include <sstream>
@@ -46,7 +46,7 @@ main (int argc, char **argv)
       return 1;
     }
 
-  CliParseFeedback feedback;
+  CliFeedback feedback;
   IniDBBuilderLint builder;
   ini_init(ini_file, &builder, feedback);
 
@@ -63,3 +63,9 @@ get_root_dir ()
   static std::string empty;
   return empty;
 }
+
+void
+fatal (HWND owner, int id, ...)
+{
+  exit(1);
+}
-- 
2.43.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH setup 08/16] Instantiate found_ini_list in ini.cc
  2024-03-08 18:34 [PATCH setup 00/16] Groundwork for a GUI-less installation tool Jon Turney
                   ` (6 preceding siblings ...)
  2024-03-08 18:34 ` [PATCH setup 07/16] Split out URL fetching progress reporting Jon Turney
@ 2024-03-08 18:34 ` Jon Turney
  2024-03-08 18:34 ` [PATCH setup 09/16] Move is_64bit to state Jon Turney
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Jon Turney @ 2024-03-08 18:34 UTC (permalink / raw)
  To: cygwin-apps; +Cc: Jon Turney

This is the list of ini files found by fromcwd.cc:do_from_local_dir().

Maybe that should be unkinked by actually doing that scan inside ini.cc,
where we could have some progress feedback?

This makes it possible to build ini.cc without fromcwd.cc
---
 fromcwd.cc | 2 --
 ini.cc     | 1 +
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/fromcwd.cc b/fromcwd.cc
index f58e955..c53eede 100644
--- a/fromcwd.cc
+++ b/fromcwd.cc
@@ -105,8 +105,6 @@ private:
   std::vector<bool> found_ini;
 };
 
-IniList found_ini_list;
-
 bool
 do_from_local_dir (HINSTANCE h, HWND owner, std::string &local_dir)
 {
diff --git a/ini.cc b/ini.cc
index 09dda13..2b2da10 100644
--- a/ini.cc
+++ b/ini.cc
@@ -56,6 +56,7 @@ std::string ini_setup_version;
 static const std::string setup_exts[] = { "zst", "xz", "bz2", "ini" };
 IniList setup_ext_list (setup_exts,
 			setup_exts + (sizeof(setup_exts) / sizeof(*setup_exts)));
+IniList found_ini_list;
 
 static BoolOption NoVerifyOption (false, 'X', "no-verify", IDS_HELPTEXT_NO_VERIFY);
 static BoolOption NoVersionCheckOption (false, '\0', "no-version-check", IDS_HELPTEXT_NO_VERSION_CHECK);
-- 
2.43.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH setup 09/16] Move is_64bit to state
  2024-03-08 18:34 [PATCH setup 00/16] Groundwork for a GUI-less installation tool Jon Turney
                   ` (7 preceding siblings ...)
  2024-03-08 18:34 ` [PATCH setup 08/16] Instantiate found_ini_list in ini.cc Jon Turney
@ 2024-03-08 18:34 ` Jon Turney
  2024-03-08 18:34 ` [PATCH setup 10/16] Move setup.ini pathame components to ini.cc Jon Turney
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Jon Turney @ 2024-03-08 18:34 UTC (permalink / raw)
  To: cygwin-apps; +Cc: Jon Turney

Note this controls what we will install, not indicating how we are
built, so it's use in splash is questionable, and is downright wrong in
the messages from IniDbBuilderPackage giving URLs for an updated
version of setup.

This controls stuff all over the place!
---
 ini.h     |  1 -
 main.cc   | 34 ++++++++++++++--------------------
 splash.cc |  2 +-
 state.cc  |  6 ++++++
 state.h   |  2 ++
 5 files changed, 23 insertions(+), 22 deletions(-)

diff --git a/ini.h b/ini.h
index f1788e2..2ca4f5b 100644
--- a/ini.h
+++ b/ini.h
@@ -23,7 +23,6 @@
 typedef std::vector <std::string> IniList;
 extern IniList found_ini_list, setup_ext_list;
 
-extern bool is_64bit;
 extern bool is_new_install;
 extern std::string SetupArch;
 extern std::string SetupIniDir;
diff --git a/main.cc b/main.cc
index 2ce3b30..c359ba9 100644
--- a/main.cc
+++ b/main.cc
@@ -83,7 +83,6 @@
 extern char **_argv;
 #endif
 
-bool is_64bit;
 bool is_new_install = false;
 std::string SetupArch;
 std::string SetupIniDir;
@@ -263,26 +262,21 @@ WinMain (HINSTANCE h,
     else if (HelpOption)
       help_option = true;
 
-    if (!((std::string) Arch).size ())
+    if (((std::string) Arch).size ())
       {
-#ifdef __x86_64__
-	is_64bit = true;
-#else
-	is_64bit = false;
-#endif
-      }
-    else if (((std::string) Arch).find ("64") != std::string::npos)
-      is_64bit = true;
-    else if (((std::string) Arch).find ("32") != std::string::npos
-	     || ((std::string) Arch).find ("x86") != std::string::npos)
-      is_64bit = false;
-    else
-      {
-	char buff[80 + ((std::string) Arch).size ()];
-	sprintf (buff, "Invalid option for --arch:  \"%s\"",
-		 ((std::string) Arch).c_str ());
-	fprintf (stderr, "*** %s\n", buff);
-	exit (1);
+        if (((std::string) Arch).find ("64") != std::string::npos)
+          is_64bit = true;
+        else if (((std::string) Arch).find ("32") != std::string::npos
+                 || ((std::string) Arch).find ("x86") != std::string::npos)
+          is_64bit = false;
+        else
+          {
+            char buff[80 + ((std::string) Arch).size ()];
+            sprintf (buff, "Invalid option for --arch:  \"%s\"",
+                     ((std::string) Arch).c_str ());
+            fprintf (stderr, "*** %s\n", buff);
+            exit (1);
+          }
       }
 
     if (GuiLangOption.isPresent())
diff --git a/splash.cc b/splash.cc
index 40c1334..8b601db 100644
--- a/splash.cc
+++ b/splash.cc
@@ -19,7 +19,7 @@
 #include "setup_version.h"
 #include "resource.h"
 #include "splash.h"
-#include "ini.h"
+#include "state.h"
 
 #define SPLASH_URL "https://cygwin.com"
 #define SPLASH_COPYRIGHT "Copyright 2000-2023"
diff --git a/state.cc b/state.cc
index 111b890..ef14116 100644
--- a/state.cc
+++ b/state.cc
@@ -29,3 +29,9 @@ int root_menu;
 int root_desktop;
 
 LANGID langid;
+
+#ifdef __x86_64__
+bool is_64bit = true;
+#else
+bool is_64bit = false;
+#endif
diff --git a/state.h b/state.h
index b211de3..c4b88a4 100644
--- a/state.h
+++ b/state.h
@@ -48,4 +48,6 @@ extern int root_desktop;
 
 extern LANGID langid;
 
+extern bool is_64bit;
+
 #endif /* SETUP_STATE_H */
-- 
2.43.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH setup 10/16] Move setup.ini pathame components to ini.cc
  2024-03-08 18:34 [PATCH setup 00/16] Groundwork for a GUI-less installation tool Jon Turney
                   ` (8 preceding siblings ...)
  2024-03-08 18:34 ` [PATCH setup 09/16] Move is_64bit to state Jon Turney
@ 2024-03-08 18:34 ` Jon Turney
  2024-03-08 18:34 ` [PATCH setup 11/16] Drop hinstance global Jon Turney
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Jon Turney @ 2024-03-08 18:34 UTC (permalink / raw)
  To: cygwin-apps; +Cc: Jon Turney

Move SetupBaseNameOption to ini.cc
Eliminate SetupIniDir, it's just SetupArch + "/"
Change SetupArch() and SetupBaseName() into functions, to avoid having
to do global initialization at the right time.
---
 fromcwd.cc |  8 ++++----
 ini.cc     | 22 +++++++++++++++++-----
 ini.h      |  5 ++---
 main.cc    |  8 --------
 4 files changed, 23 insertions(+), 20 deletions(-)

diff --git a/fromcwd.cc b/fromcwd.cc
index c53eede..b1f1021 100644
--- a/fromcwd.cc
+++ b/fromcwd.cc
@@ -52,7 +52,7 @@ public:
 	     ext != setup_ext_list.end ();
 	     ext++, fi++)
 	  {
-	    if (!casecompare (SetupBaseName + "." + *ext,  theFile->cFileName))
+	    if (!casecompare (SetupBaseName() + "." + *ext,  theFile->cFileName))
 	      *fi = true;
 	  }
       }
@@ -62,7 +62,7 @@ public:
   {
     if (level <= 0)
       return;
-    inidir = !casecompare (SetupArch, aDir->cFileName);
+    inidir = !casecompare (SetupArch(), aDir->cFileName);
     if (level == 1 && !inidir)
       return;
     Find aFinder (basePath + aDir->cFileName);
@@ -74,8 +74,8 @@ public:
 	  {
 	    if (*fi)
 	      {
-		found_ini_list.push_back (basePath + SetupArch + "/"
-					  + SetupBaseName + "." + *ext);
+		found_ini_list.push_back (basePath + SetupArch() + "/"
+					  + SetupBaseName() + "." + *ext);
 		/* 
 		 * Terminate the search after the first setup file
 		 * found, which shadows any setup files with
diff --git a/ini.cc b/ini.cc
index 2b2da10..42df6a3 100644
--- a/ini.cc
+++ b/ini.cc
@@ -44,6 +44,7 @@
 #include "io_stream_memory.h"
 
 #include "getopt++/BoolOption.h"
+#include "getopt++/StringOption.h"
 #include "IniDBBuilderPackage.h"
 #include "compress.h"
 #include "msg.h"
@@ -58,10 +59,21 @@ IniList setup_ext_list (setup_exts,
 			setup_exts + (sizeof(setup_exts) / sizeof(*setup_exts)));
 IniList found_ini_list;
 
+static StringOption SetupBaseNameOption ("setup", 'i', "ini-basename", IDS_HELPTEXT_INI_BASENAME, false);
 static BoolOption NoVerifyOption (false, 'X', "no-verify", IDS_HELPTEXT_NO_VERIFY);
 static BoolOption NoVersionCheckOption (false, '\0', "no-version-check", IDS_HELPTEXT_NO_VERSION_CHECK);
 
 
+std::string SetupArch()
+{
+  return is_64bit ? "x86_64" : "x86";
+}
+
+std::string SetupBaseName()
+{
+  return SetupBaseNameOption;
+}
+
 static io_stream*
 decompress_ini (io_stream *ini_file, std::string &current_ini_name)
 {
@@ -170,7 +182,7 @@ do_local_ini (Feedback &myFeedback)
       if (!ini_file || sig_fail)
 	{
 	  // no setup found or signature invalid
-	  note (myFeedback.owner(), IDS_SETUPINI_MISSING, SetupBaseName.c_str (),
+	  note (myFeedback.owner(), IDS_SETUPINI_MISSING, SetupBaseName().c_str (),
 		"localdir");
 	  ini_error = true;
 	}
@@ -180,7 +192,7 @@ do_local_ini (Feedback &myFeedback)
 	  myFeedback.babble ("Found ini file - " + current_ini_name);
 	  myFeedback.iniName (current_ini_name);
 	  int ldl = local_dir.length () + 1;
-	  int cap = current_ini_name.rfind ("/" + SetupArch);
+	  int cap = current_ini_name.rfind ("/" + SetupArch());
 	  aBuilder.parse_mirror =
 	    rfc1738_unescape (current_ini_name.substr (ldl, cap - ldl));
 	  ini_init (ini_file, &aBuilder, myFeedback);
@@ -225,7 +237,7 @@ do_remote_ini (Feedback &myFeedback)
 	   ext++)
 	{
 	  current_ini_ext = *ext;
-	  current_ini_name = n->url + SetupIniDir + SetupBaseName + "." + current_ini_ext;
+	  current_ini_name = n->url + SetupArch() + "/" + SetupBaseName() + "." + current_ini_ext;
 	  current_ini_sig_name = current_ini_name + ".sig";
 	  ini_sig_file = get_url_to_membuf (current_ini_sig_name, myFeedback);
 	  ini_file = get_url_to_membuf (current_ini_name, myFeedback);
@@ -240,7 +252,7 @@ do_remote_ini (Feedback &myFeedback)
       if (!ini_file || sig_fail)
 	{
 	  // no setup found or signature invalid
-	  note (myFeedback.owner(), IDS_SETUPINI_MISSING, SetupBaseName.c_str (), n->url.c_str ());
+	  note (myFeedback.owner(), IDS_SETUPINI_MISSING, SetupBaseName().c_str (), n->url.c_str ());
 	  ini_error = true;
 	}
       else
@@ -260,7 +272,7 @@ do_remote_ini (Feedback &myFeedback)
 	      /* save known-good setup.ini locally */
 	      const std::string fp = "file://" + local_dir + "/" +
 				      rfc1738_escape_part (n->url) +
-				      "/" + SetupIniDir + SetupBaseName + ".ini";
+				      "/" + SetupArch() + "/" + SetupBaseName() + ".ini";
 	      io_stream::mkpath_p (PATH_TO_FILE, fp, 0);
 	      if (io_stream *out = io_stream::open (fp, "wb", 0))
 		{
diff --git a/ini.h b/ini.h
index 2ca4f5b..05b31e0 100644
--- a/ini.h
+++ b/ini.h
@@ -24,9 +24,8 @@ typedef std::vector <std::string> IniList;
 extern IniList found_ini_list, setup_ext_list;
 
 extern bool is_new_install;
-extern std::string SetupArch;
-extern std::string SetupIniDir;
-extern std::string SetupBaseName;
+std::string SetupArch();
+std::string SetupBaseName();
 
 class io_stream;
 class IniDBBuilder;
diff --git a/main.cc b/main.cc
index c359ba9..4c391f5 100644
--- a/main.cc
+++ b/main.cc
@@ -84,7 +84,6 @@ extern char **_argv;
 #endif
 
 bool is_new_install = false;
-std::string SetupArch;
 std::string SetupIniDir;
 
 HINSTANCE hinstance;
@@ -109,14 +108,11 @@ static BoolOption NoAdminOption (false, 'B', "no-admin", IDS_HELPTEXT_NO_ADMIN);
 static BoolOption WaitOption (false, 'W', "wait", IDS_HELPTEXT_WAIT);
 static BoolOption HelpOption (false, 'h', "help", IDS_HELPTEXT_HELP);
 static BoolOption VersionOption (false, 'V', "version", IDS_HELPTEXT_VERSION);
-static StringOption SetupBaseNameOpt ("setup", 'i', "ini-basename", IDS_HELPTEXT_INI_BASENAME, false);
 BoolOption UnsupportedOption (false, '\0', "allow-unsupported-windows", IDS_HELPTEXT_ALLOW_UNSUPPORTED_WINDOWS);
 static BoolOption DeprecatedOption (false, 'w', "no-warn-deprecated-windows", IDS_HELPTEXT_NO_WARN_DEPRECATED_WINDOWS);
 static StringChoiceOption SymlinkTypeOption(symlink_types, '\0', "symlink-type", IDS_HELPTEXT_SYMLINK_TYPE, false, SymlinkTypeMagic);
 static StringOption GuiLangOption ("", '\0', "lang", IDS_HELPTEXT_LANG);
 
-std::string SetupBaseName;
-
 static void inline
 set_cout ()
 {
@@ -298,10 +294,6 @@ WinMain (HINSTANCE h,
 
     bool output_only = help_option || VersionOption;
 
-    SetupBaseName = SetupBaseNameOpt;
-    SetupArch = is_64bit ? "x86_64" : "x86";
-    SetupIniDir = SetupArch+"/";
-
     /* Initialize well known SIDs.  We need the admin SID to test if we're
        supposed to elevate. */
     nt_sec.initialiseWellKnownSIDs ();
-- 
2.43.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH setup 11/16] Drop hinstance global
  2024-03-08 18:34 [PATCH setup 00/16] Groundwork for a GUI-less installation tool Jon Turney
                   ` (9 preceding siblings ...)
  2024-03-08 18:34 ` [PATCH setup 10/16] Move setup.ini pathame components to ini.cc Jon Turney
@ 2024-03-08 18:34 ` Jon Turney
  2024-03-08 18:34 ` [PATCH setup 12/16] Spit out GetNetAuth from NetIO Jon Turney
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Jon Turney @ 2024-03-08 18:34 UTC (permalink / raw)
  To: cygwin-apps; +Cc: Jon Turney

We do not need to retain the hInstance value passed into WinMain(), as
it's always available as GetModuleHandle(NULL).

Note that DialogBox() accepts NULL meaning "the current executable" in
any case.

Future work: there's still some completely unnecessary storing it in
class Window and passing it around.
---
 dialog.h        |  3 ---
 gui/SitePage.cc |  3 +--
 install.cc      |  2 +-
 main.cc         |  5 +----
 msg.cc          |  5 ++---
 netio.cc        | 10 +++++-----
 6 files changed, 10 insertions(+), 18 deletions(-)

diff --git a/dialog.h b/dialog.h
index 63c98ee..ebbf661 100644
--- a/dialog.h
+++ b/dialog.h
@@ -20,9 +20,6 @@
 
 #include "win32.h"
 
-/* global instance for the application; set in main.cc */
-extern HINSTANCE hinstance;
-
 /* used by main.cc to select the next do_* function */
 extern int next_dialog;
 
diff --git a/gui/SitePage.cc b/gui/SitePage.cc
index 1cdb1bf..9dacebc 100644
--- a/gui/SitePage.cc
+++ b/gui/SitePage.cc
@@ -367,8 +367,7 @@ int check_dropped_mirrors (HWND h)
     {
       if (unattended_mode)
 	return CACHE_ACCEPT_WARN;
-      return DialogBox (hinstance, MAKEINTRESOURCE (IDD_DROPPED), h,
-			drop_proc);
+      return DialogBox (NULL, MAKEINTRESOURCE (IDD_DROPPED), h, drop_proc);
     }
   return CACHE_ACCEPT_NOWARN;
 }
diff --git a/install.cc b/install.cc
index 628dbd0..001529b 100644
--- a/install.cc
+++ b/install.cc
@@ -660,7 +660,7 @@ Installer::_installOne (packagemeta &pkgm,
                             dlg_data.processlist = plm.c_str ();
                             dlg_data.iteration = iteration;
 
-                            rc = DialogBoxParam(hinstance, MAKEINTRESOURCE (IDD_FILE_INUSE), owner, FileInuseDlgProc, (LPARAM)&dlg_data);
+                            rc = DialogBoxParam(NULL, MAKEINTRESOURCE (IDD_FILE_INUSE), owner, FileInuseDlgProc, (LPARAM)&dlg_data);
                           }
                         else
                           {
diff --git a/main.cc b/main.cc
index 4c391f5..8a68232 100644
--- a/main.cc
+++ b/main.cc
@@ -86,8 +86,6 @@ extern char **_argv;
 bool is_new_install = false;
 std::string SetupIniDir;
 
-HINSTANCE hinstance;
-
 static StringChoiceOption::StringChoices symlink_types({
     {"native", SymlinkTypeNative},
     {"lnk", SymlinkTypeShortcut},
@@ -176,7 +174,7 @@ main_display ()
     }
 
   // Init window class lib
-  Window::SetAppInstance (hinstance);
+  Window::SetAppInstance (GetModuleHandle(NULL));
 
   // Create pages
   Splash.Create ();
@@ -221,7 +219,6 @@ int WINAPI
 WinMain (HINSTANCE h,
 	 HINSTANCE hPrevInstance, LPSTR command_line, int cmd_show)
 {
-  hinstance = h;
 
   // Make sure Windows DLLs only delay-load further DLLs from System32
   typedef BOOL (WINAPI *PFNSETDEFAULTDLLDIRECTORIES)(DWORD);
diff --git a/msg.cc b/msg.cc
index 8e344ff..b53df86 100644
--- a/msg.cc
+++ b/msg.cc
@@ -23,7 +23,6 @@
 
 #include <stdio.h>
 #include <stdarg.h>
-#include "dialog.h"
 #include "state.h"
 #include "String++.h"
 #include "resource.h"
@@ -66,7 +65,7 @@ mbox (HWND owner, const char *buf, const char *name, int type)
     }
 
   char caption[32];
-  LoadString (hinstance, IDS_MBOX_CAPTION, caption, sizeof (caption));
+  LoadString (GetModuleHandle(NULL), IDS_MBOX_CAPTION, caption, sizeof (caption));
 
   return MessageBox (owner, buf, caption, type);
 }
@@ -76,7 +75,7 @@ mbox (HWND owner, const char *name, int type, int id, va_list args)
 {
   char buf[1000], fmt[1000];
 
-  if (LoadString (hinstance, id, fmt, sizeof (fmt)) <= 0)
+  if (LoadString (GetModuleHandle(NULL), id, fmt, sizeof (fmt)) <= 0)
     ExitProcess (0);
 
   vsnprintf (buf, 1000, fmt, args);
diff --git a/netio.cc b/netio.cc
index 631532a..d6bfc24 100644
--- a/netio.cc
+++ b/netio.cc
@@ -185,9 +185,9 @@ auth_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
 }
 
 static int
-auth_common (HINSTANCE h, int id, HWND owner)
+auth_common (int id, HWND owner)
 {
-  return DialogBox (h, MAKEINTRESOURCE (id), owner, auth_proc);
+  return DialogBox (NULL, MAKEINTRESOURCE (id), owner, auth_proc);
 }
 
 int
@@ -195,7 +195,7 @@ NetIO::get_auth (HWND owner)
 {
   user = &net_user;
   passwd = &net_passwd;
-  return auth_common (hinstance, IDD_NET_AUTH, owner);
+  return auth_common (IDD_NET_AUTH, owner);
 }
 
 int
@@ -203,7 +203,7 @@ NetIO::get_proxy_auth (HWND owner)
 {
   user = &net_proxy_user;
   passwd = &net_proxy_passwd;
-  return auth_common (hinstance, IDD_PROXY_AUTH, owner);
+  return auth_common (IDD_PROXY_AUTH, owner);
 }
 
 int
@@ -221,7 +221,7 @@ NetIO::get_ftp_auth (HWND owner)
     }
   user = &net_ftp_user;
   passwd = &net_ftp_passwd;
-  return auth_common (hinstance, IDD_FTP_AUTH, owner);
+  return auth_common (IDD_FTP_AUTH, owner);
 }
 
 const char *
-- 
2.43.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH setup 12/16] Spit out GetNetAuth from NetIO
  2024-03-08 18:34 [PATCH setup 00/16] Groundwork for a GUI-less installation tool Jon Turney
                   ` (10 preceding siblings ...)
  2024-03-08 18:34 ` [PATCH setup 11/16] Drop hinstance global Jon Turney
@ 2024-03-08 18:34 ` Jon Turney
  2024-03-08 18:34 ` [PATCH setup 13/16] Split out hash checking progress reporting Jon Turney
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Jon Turney @ 2024-03-08 18:34 UTC (permalink / raw)
  To: cygwin-apps; +Cc: Jon Turney

There's still all kinds of janky stuff here: The network proxy
configuration fetched by ConnectionSetting is stored into static members
of the NetIO class, rather than held there and accessed.

Again, define a virtual class as the interface through which user
interaction takes place, and implement that for GUI and CLI clients.

While we're at it, we arrange for the GUI dialogs for network auth to be
properly parented.
---
 GetNetAuth.h         |  30 ++++++++++
 Makefile.am          |   2 +
 cli/CliGetNetAuth.cc |  45 ++++++++++++++
 cli/CliGetNetAuth.h  |  32 ++++++++++
 gui/GuiGetNetAuth.cc | 138 +++++++++++++++++++++++++++++++++++++++++++
 gui/GuiGetNetAuth.h  |  38 ++++++++++++
 net.cc               |   5 ++
 netio.cc             | 125 +--------------------------------------
 netio.h              |  19 ++----
 nio-ie5.cc           |   4 +-
 10 files changed, 298 insertions(+), 140 deletions(-)
 create mode 100644 GetNetAuth.h
 create mode 100644 cli/CliGetNetAuth.cc
 create mode 100644 cli/CliGetNetAuth.h
 create mode 100644 gui/GuiGetNetAuth.cc
 create mode 100644 gui/GuiGetNetAuth.h

diff --git a/GetNetAuth.h b/GetNetAuth.h
new file mode 100644
index 0000000..0a26e85
--- /dev/null
+++ b/GetNetAuth.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2000, Red Hat, Inc.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     A copy of the GNU General Public License can be found at
+ *     http://www.gnu.org/
+ *
+ * Written by DJ Delorie <dj@cygnus.com>
+ *
+ */
+
+#ifndef SETUP_GETNETAUTH_H
+#define SETUP_GETNETAUTH_H
+
+class GetNetAuth
+{
+public:
+  /* Helper functions for http/ftp protocols.  Both return nonzero for
+     "cancel", zero for "ok".  They set net_proxy_user, etc, in
+     state.h */
+  virtual int get_auth () = 0;
+  virtual int get_proxy_auth () = 0;
+  virtual int get_ftp_auth () = 0;
+};
+
+#endif /* SETUP_GETNETAUTH_H */
diff --git a/Makefile.am b/Makefile.am
index de066b7..f257e3a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -182,6 +182,8 @@ endif
 	gpg-packet.cc \
 	gpg-packet.h \
 	gui/GuiParseFeedback.cc \
+	gui/GuiGetNetAuth.cc \
+	gui/GuiGetNetAuth.h \
 	gui/GuiGetUrlFeedback.cc \
 	gui/GuiFeedback.h \
 	ini.cc \
diff --git a/cli/CliGetNetAuth.cc b/cli/CliGetNetAuth.cc
new file mode 100644
index 0000000..a1fde3b
--- /dev/null
+++ b/cli/CliGetNetAuth.cc
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2000, 2001, Red Hat, Inc.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     A copy of the GNU General Public License can be found at
+ *     http://www.gnu.org/
+ *
+ */
+
+/* Query user for auth information required */
+
+#include "netio.h"
+#include "CliGetNetAuth.h"
+
+#include "LogFile.h"
+
+static int
+auth_common(const char *mode)
+{
+  Log (LOG_PLAIN) << mode << " not implemented" << endLog;
+  Logger ().exit (1);
+  return 1;
+}
+
+int
+CliGetNetAuth::get_auth ()
+{
+  return auth_common("get_auth");
+}
+
+int
+CliGetNetAuth::get_proxy_auth ()
+{
+  return auth_common("get_proxy_auth");
+}
+
+int
+CliGetNetAuth::get_ftp_auth ()
+{
+  return auth_common("get_ftp_auth");
+}
diff --git a/cli/CliGetNetAuth.h b/cli/CliGetNetAuth.h
new file mode 100644
index 0000000..7ff4520
--- /dev/null
+++ b/cli/CliGetNetAuth.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2000, Red Hat, Inc.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     A copy of the GNU General Public License can be found at
+ *     http://www.gnu.org/
+ *
+ * Written by DJ Delorie <dj@cygnus.com>
+ *
+ */
+
+#ifndef SETUP_CLI_GETNETAUTH_H
+#define SETUP_CLI_GETNETAUTH_H
+
+#include "GetNetAuth.h"
+
+class CliGetNetAuth : public GetNetAuth
+{
+public:
+  /* Helper functions for http/ftp protocols.  Both return nonzero for
+     "cancel", zero for "ok".  They set net_proxy_user, etc, in
+     state.h */
+  int get_auth ();
+  int get_proxy_auth ();
+  int get_ftp_auth ();
+};
+
+#endif /* SETUP_CLI_GETNETAUTH_H */
diff --git a/gui/GuiGetNetAuth.cc b/gui/GuiGetNetAuth.cc
new file mode 100644
index 0000000..a6d4917
--- /dev/null
+++ b/gui/GuiGetNetAuth.cc
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2000, 2001, Red Hat, Inc.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     A copy of the GNU General Public License can be found at
+ *     http://www.gnu.org/
+ *
+ */
+
+/* Query user for auth information required */
+
+#include "netio.h"
+#include "GuiGetNetAuth.h"
+
+#include "LogFile.h"
+
+#include "resource.h"
+#include "dialog.h"
+
+static char **user, **passwd;
+static int loading = 0;
+
+static void
+check_if_enable_ok (HWND h)
+{
+  int e = 0;
+  if (*user)
+    e = 1;
+  EnableWindow (GetDlgItem (h, IDOK), e);
+}
+
+static void
+load_dialog (HWND h)
+{
+  loading = 1;
+  eset (h, IDC_NET_USER, *user);
+  eset (h, IDC_NET_PASSWD, *passwd);
+  check_if_enable_ok (h);
+  loading = 0;
+}
+
+static void
+save_dialog (HWND h)
+{
+  *user = eget (h, IDC_NET_USER, *user);
+  *passwd = eget (h, IDC_NET_PASSWD, *passwd);
+  if (! *passwd) {
+    *passwd = new char[1];
+    (*passwd)[0] = '\0';
+  }
+}
+
+static BOOL
+auth_cmd (HWND h, int id, HWND hwndctl, UINT code)
+{
+  switch (id)
+    {
+
+    case IDC_NET_USER:
+    case IDC_NET_PASSWD:
+      if (code == EN_CHANGE && !loading)
+	{
+	  save_dialog (h);
+	  check_if_enable_ok (h);
+	}
+      break;
+
+    case IDOK:
+      save_dialog (h);
+      EndDialog (h, 0);
+      break;
+
+    case IDCANCEL:
+      EndDialog (h, 1);
+      Logger ().exit (1);
+      break;
+    }
+  return 0;
+}
+
+static INT_PTR CALLBACK
+auth_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  switch (message)
+    {
+    case WM_INITDIALOG:
+      load_dialog (h);
+      return FALSE;
+    case WM_COMMAND:
+      auth_cmd (h, LOWORD(wParam), (HWND)lParam, HIWORD(wParam));
+      return 0;
+    }
+  return FALSE;
+}
+
+static int
+auth_common (int id, HWND owner)
+{
+  return DialogBox (NULL, MAKEINTRESOURCE (id), owner, auth_proc);
+}
+
+int
+GuiGetNetAuth::get_auth ()
+{
+  user = &NetIO::net_user;
+  passwd = &NetIO::net_passwd;
+  return auth_common (IDD_NET_AUTH, owner);
+}
+
+int
+GuiGetNetAuth::get_proxy_auth ()
+{
+  user = &NetIO::net_proxy_user;
+  passwd = &NetIO::net_proxy_passwd;
+  return auth_common (IDD_PROXY_AUTH, owner);
+}
+
+int
+GuiGetNetAuth::get_ftp_auth ()
+{
+  if (NetIO::net_ftp_user)
+    {
+      delete[] NetIO::net_ftp_user;
+      NetIO::net_ftp_user = NULL;
+    }
+  if (NetIO::net_ftp_passwd)
+    {
+      delete[] NetIO::net_ftp_passwd;
+      NetIO::net_ftp_passwd = NULL;
+    }
+  user = &NetIO::net_ftp_user;
+  passwd = &NetIO::net_ftp_passwd;
+  return auth_common (IDD_FTP_AUTH, owner);
+}
diff --git a/gui/GuiGetNetAuth.h b/gui/GuiGetNetAuth.h
new file mode 100644
index 0000000..21758f2
--- /dev/null
+++ b/gui/GuiGetNetAuth.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2000, Red Hat, Inc.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     A copy of the GNU General Public License can be found at
+ *     http://www.gnu.org/
+ *
+ * Written by DJ Delorie <dj@cygnus.com>
+ *
+ */
+
+#ifndef SETUP_GUI_GETNETAUTH_H
+#define SETUP_GUI_GETNETAUTH_H
+
+#include "win32.h"
+#include "GetNetAuth.h"
+
+class GuiGetNetAuth : public GetNetAuth
+{
+public:
+  GuiGetNetAuth (HWND owner_) : owner(owner_) { };
+
+  /* Helper functions for http/ftp protocols.  Both return nonzero for
+     "cancel", zero for "ok".  They set net_proxy_user, etc, in
+     state.h */
+  int get_auth ();
+  int get_proxy_auth ();
+  int get_ftp_auth ();
+
+private:
+  HWND owner;
+};
+
+#endif /* SETUP_GUI_GETNETAUTH_H */
diff --git a/net.cc b/net.cc
index f460efc..ee84e64 100644
--- a/net.cc
+++ b/net.cc
@@ -33,6 +33,8 @@
 #include "propsheet.h"
 #include "threebar.h"
 #include "ConnectionSetting.h"
+#include "gui/GuiGetNetAuth.h"
+
 extern ThreeBarProgressPage Progress;
 
 static StringOption ProxyOption ("", 'p', "proxy", IDS_HELPTEXT_PROXY, false);
@@ -113,6 +115,9 @@ NetPage::OnInit ()
   if (!NetIO::net_method)
     NetIO::net_method = IDC_NET_PRECONFIG;
 
+  // install the interactive network auth getter
+  NetIO::auth_getter = new GuiGetNetAuth(GetHWND());
+
   if (proxyString.size ())
   {
     unsigned int pos = proxyString.find_last_of (':');
diff --git a/netio.cc b/netio.cc
index d6bfc24..7d32f9f 100644
--- a/netio.cc
+++ b/netio.cc
@@ -21,17 +21,10 @@
 
 #include "LogFile.h"
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
 #include <shlwapi.h>
 
 #include "resource.h"
-#include "state.h"
-#include "msg.h"
 #include "nio-ie5.h"
-#include "dialog.h"
 
 int NetIO::net_method;
 char *NetIO::net_proxy_host;
@@ -43,6 +36,7 @@ char *NetIO::net_proxy_user;
 char *NetIO::net_proxy_passwd;
 char *NetIO::net_ftp_user;
 char *NetIO::net_ftp_passwd;
+GetNetAuth *NetIO::auth_getter;
 
 int
 NetIO::ok ()
@@ -107,123 +101,6 @@ NetIO::open (char const *url, bool cachable)
   return rv;
 }
 
-
-static char **user, **passwd;
-static int loading = 0;
-
-static void
-check_if_enable_ok (HWND h)
-{
-  int e = 0;
-  if (*user)
-    e = 1;
-  EnableWindow (GetDlgItem (h, IDOK), e);
-}
-
-static void
-load_dialog (HWND h)
-{
-  loading = 1;
-  eset (h, IDC_NET_USER, *user);
-  eset (h, IDC_NET_PASSWD, *passwd);
-  check_if_enable_ok (h);
-  loading = 0;
-}
-
-static void
-save_dialog (HWND h)
-{
-  *user = eget (h, IDC_NET_USER, *user);
-  *passwd = eget (h, IDC_NET_PASSWD, *passwd);
-  if (! *passwd) {
-    *passwd = new char[1];
-    (*passwd)[0] = '\0';
-  }
-}
-
-static BOOL
-auth_cmd (HWND h, int id, HWND hwndctl, UINT code)
-{
-  switch (id)
-    {
-
-    case IDC_NET_USER:
-    case IDC_NET_PASSWD:
-      if (code == EN_CHANGE && !loading)
-	{
-	  save_dialog (h);
-	  check_if_enable_ok (h);
-	}
-      break;
-
-    case IDOK:
-      save_dialog (h);
-      EndDialog (h, 0);
-      break;
-
-    case IDCANCEL:
-      EndDialog (h, 1);
-      Logger ().exit (1);
-      break;
-    }
-  return 0;
-}
-
-static INT_PTR CALLBACK
-auth_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
-{
-  switch (message)
-    {
-    case WM_INITDIALOG:
-      load_dialog (h);
-      return FALSE;
-    case WM_COMMAND:
-      auth_cmd (h, LOWORD(wParam), (HWND)lParam, HIWORD(wParam));
-      return 0;
-    }
-  return FALSE;
-}
-
-static int
-auth_common (int id, HWND owner)
-{
-  return DialogBox (NULL, MAKEINTRESOURCE (id), owner, auth_proc);
-}
-
-int
-NetIO::get_auth (HWND owner)
-{
-  user = &net_user;
-  passwd = &net_passwd;
-  return auth_common (IDD_NET_AUTH, owner);
-}
-
-int
-NetIO::get_proxy_auth (HWND owner)
-{
-  user = &net_proxy_user;
-  passwd = &net_proxy_passwd;
-  return auth_common (IDD_PROXY_AUTH, owner);
-}
-
-int
-NetIO::get_ftp_auth (HWND owner)
-{
-  if (net_ftp_user)
-    {
-      delete[] net_ftp_user;
-      net_ftp_user = NULL;
-    }
-  if (net_ftp_passwd)
-    {
-      delete[] net_ftp_passwd;
-      net_ftp_passwd = NULL;
-    }
-  user = &net_ftp_user;
-  passwd = &net_ftp_passwd;
-  return auth_common (IDD_FTP_AUTH, owner);
-}
-
 const char *
 NetIO::net_method_name ()
 {
diff --git a/netio.h b/netio.h
index f2ecfdd..98d435b 100644
--- a/netio.h
+++ b/netio.h
@@ -16,23 +16,22 @@
 #ifndef SETUP_NETIO_H
 #define SETUP_NETIO_H
 
-#include "win32.h"
+#include "GetNetAuth.h"
 
 /* This is the parent class for all the access methods known to setup
    (i.e. ways to download files from the internet or other sources */
 
 class NetIO
 {
-protected:
+public:
   static char *net_user;
   static char *net_passwd;
   static char *net_proxy_user;
   static char *net_proxy_passwd;
   static char *net_ftp_user;
   static char *net_ftp_passwd;
+  static GetNetAuth *auth_getter;
 
-
-public:
   /* if nonzero, this is the estimated total file size */
   int file_size;
 
@@ -40,9 +39,8 @@ public:
   virtual ~ NetIO () {};
 
   /* The user calls this function to create a suitable accessor for
-     the given URL.  It uses the network setup state in state.h.  If
-     anything fails, either the return values is NULL or the returned
-     object is !ok() */
+     the given URL. If anything fails, either the return values is NULL
+     or the returned object is !ok() */
   static NetIO *open (char const *url, bool cachable);
 
   /* If !ok() that means the transfer isn't happening. */
@@ -57,13 +55,6 @@ public:
   static int net_proxy_port;
 
   static const char *net_method_name();
-
-  /* Helper functions for http/ftp protocols.  Both return nonzero for
-     "cancel", zero for "ok".  They set net_proxy_user, etc, in
-     state.h */
-  int get_auth (HWND owner);
-  int get_proxy_auth (HWND owner);
-  int get_ftp_auth (HWND owner);
 };
 
 #endif /* SETUP_NETIO_H */
diff --git a/nio-ie5.cc b/nio-ie5.cc
index 2117e33..2c7e85a 100644
--- a/nio-ie5.cc
+++ b/nio-ie5.cc
@@ -274,14 +274,14 @@ try_again:
 	  if (type == 401)	/* authorization required */
 	    {
 	      flush_io ();
-	      get_auth (NULL);
+	      auth_getter->get_auth ();
 	      resend = 1;
 	      goto try_again;
 	    }
 	  else if (type == 407)	/* proxy authorization required */
 	    {
 	      flush_io ();
-	      get_proxy_auth (NULL);
+	      auth_getter->get_proxy_auth ();
 	      resend = 1;
 	      goto try_again;
 	    }
-- 
2.43.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH setup 13/16] Split out hash checking progress reporting
  2024-03-08 18:34 [PATCH setup 00/16] Groundwork for a GUI-less installation tool Jon Turney
                   ` (11 preceding siblings ...)
  2024-03-08 18:34 ` [PATCH setup 12/16] Spit out GetNetAuth from NetIO Jon Turney
@ 2024-03-08 18:34 ` Jon Turney
  2024-03-08 18:34 ` [PATCH setup 14/16] Push check_for_cached into package_source Jon Turney
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Jon Turney @ 2024-03-08 18:34 UTC (permalink / raw)
  To: cygwin-apps; +Cc: Jon Turney

---
 Feedback.h                  |  4 ++++
 Makefile.am                 |  2 ++
 choose.cc                   |  4 +++-
 cli/CliFeedback.h           |  5 +++++
 cli/CliHashCheckFeedback.cc | 30 ++++++++++++++++++++++++++++++
 download.cc                 | 24 ++++++++++++------------
 download.h                  |  6 +++---
 gui/GuiFeedback.h           |  5 +++++
 gui/GuiHashCheckFeedback.cc | 34 ++++++++++++++++++++++++++++++++++
 install.cc                  |  4 +++-
 package_db.cc               |  6 +++---
 package_db.h                |  3 ++-
 package_meta.cc             | 10 +++++-----
 package_meta.h              |  5 +++--
 package_source.cc           | 33 ++++++++++-----------------------
 package_source.h            |  8 +++++---
 16 files changed, 129 insertions(+), 54 deletions(-)
 create mode 100644 cli/CliHashCheckFeedback.cc
 create mode 100644 gui/GuiHashCheckFeedback.cc

diff --git a/Feedback.h b/Feedback.h
index 8f603a6..4db7c4a 100644
--- a/Feedback.h
+++ b/Feedback.h
@@ -47,6 +47,10 @@ public:
   virtual void fetch_finish (int total_bytes) = 0;
   virtual void fetch_fatal (const char *filename, const char *err) = 0;
 
+  // hash checking
+  virtual void hash_init (const char *hashalg, const std::string &url) = 0;
+  virtual void hash_progress (int bytes, int total_bytes) = 0;
+
   //
   virtual HWND owner () = 0;
 };
diff --git a/Makefile.am b/Makefile.am
index f257e3a..def20a4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -67,6 +67,7 @@ inilint_SOURCES = \
 	filemanip.h \
 	cli/CliParseFeedback.cc \
 	cli/CliGetUrlFeedback.cc \
+	cli/CliHashCheckFeedback.cc \
 	cli/CliFeedback.h \
 	LogSingleton.cc \
 	LogSingleton.h \
@@ -186,6 +187,7 @@ endif
 	gui/GuiGetNetAuth.h \
 	gui/GuiGetUrlFeedback.cc \
 	gui/GuiFeedback.h \
+	gui/GuiHashCheckFeedback.cc \
 	ini.cc \
 	ini.h \
 	IniDBBuilder.h \
diff --git a/choose.cc b/choose.cc
index 8deab87..451b390 100644
--- a/choose.cc
+++ b/choose.cc
@@ -50,6 +50,7 @@
 #include "package_meta.h"
 
 #include "threebar.h"
+#include "gui/GuiFeedback.h"
 #include "Generic.h"
 #include "ControlAdjuster.h"
 #include "prereq.h"
@@ -317,9 +318,10 @@ void
 ChooserPage::OnActivate()
 {
   SetBusy();
+  GuiFeedback feedback(GetHWND());
 
   packagedb db;
-  db.prep();
+  db.prep(feedback);
 
   if (!activated)
     {
diff --git a/cli/CliFeedback.h b/cli/CliFeedback.h
index 3bcc23c..cb59650 100644
--- a/cli/CliFeedback.h
+++ b/cli/CliFeedback.h
@@ -48,6 +48,11 @@ private:
   unsigned int last_tics;
   unsigned int start_tics;
 
+  // hash checking
+public:
+  void hash_init (const char *hashalg, const std::string &url);
+  void hash_progress (int bytes, int total_bytes);
+
   // owner
 public:
   HWND owner () { return NULL; }
diff --git a/cli/CliHashCheckFeedback.cc b/cli/CliHashCheckFeedback.cc
new file mode 100644
index 0000000..f5df9fc
--- /dev/null
+++ b/cli/CliHashCheckFeedback.cc
@@ -0,0 +1,30 @@
+/*
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     A copy of the GNU General Public License can be found at
+ *     http://www.gnu.org/
+ *
+ */
+
+#include "cli/CliFeedback.h"
+#include "resource.h"
+#include "String++.h"
+#include <iostream>
+
+void
+CliFeedback::hash_init(const char *hashalg, const std::string &shortname)
+{
+  std::wstring fmt = LoadStringW(IDS_PROGRESS_CHECKING_HASH);
+  std::wstring s = format(fmt, hashalg, shortname.c_str());
+  std::cout << wstring_to_string(s) << std::endl;
+}
+
+void
+CliFeedback::hash_progress(int bytes, int total_bytes)
+{
+  std::cout << bytes << "/" << total_bytes << "\r";
+}
diff --git a/download.cc b/download.cc
index 02fd484..fbe36e5 100644
--- a/download.cc
+++ b/download.cc
@@ -52,14 +52,14 @@ extern ThreeBarProgressPage Progress;
 // user chooses to delete the file; otherwise throw an exception.
 static bool
 validateCachedPackage (const std::string& fullname, packagesource & pkgsource,
-		       HWND owner, bool check_hash, bool check_size)
+                       Feedback &feedback, bool check_hash, bool check_size)
 {
   try
     {
       if (check_size)
 	pkgsource.check_size_and_cache (fullname);
       if (check_hash)
-	pkgsource.check_hash ();
+	pkgsource.check_hash (feedback);
       return true;
     }
   catch (Exception *e)
@@ -69,7 +69,7 @@ validateCachedPackage (const std::string& fullname, packagesource & pkgsource,
       if (strncmp (filename, "file://", 7) == 0)
 	filename += 7;
       if (e->errNo() == APPERR_CORRUPT_PACKAGE
-	  && yesno (owner, IDS_QUERY_CORRUPT, filename) == IDYES)
+	  && yesno (feedback.owner(), IDS_QUERY_CORRUPT, filename) == IDYES)
 	remove (filename);
       else
 	throw e;
@@ -80,8 +80,8 @@ validateCachedPackage (const std::string& fullname, packagesource & pkgsource,
 /* 0 if not cached; may throw exception if validation fails.
  */
 int
-check_for_cached (packagesource & pkgsource, HWND owner, bool mirror_mode,
-		  bool check_hash)
+check_for_cached (packagesource & pkgsource, Feedback &feedback,
+                  bool mirror_mode, bool check_hash)
 {
   /* If the packagesource doesn't have a filename, it can't possibly be in the
      cache */
@@ -105,7 +105,7 @@ check_for_cached (packagesource & pkgsource, HWND owner, bool mirror_mode,
   // Already found one, which we can assume to have the right size.
   if (pkgsource.Cached())
     {
-      if (validateCachedPackage (pkgsource.Cached(), pkgsource, owner,
+      if (validateCachedPackage (pkgsource.Cached(), pkgsource, feedback,
 				 check_hash, false))
 	return 1;
       // If we get here, pkgsource.Cached() was corrupt and deleted.
@@ -117,7 +117,7 @@ check_for_cached (packagesource & pkgsource, HWND owner, bool mirror_mode,
   */
   if (io_stream::exists (fullname))
     {
-      if (validateCachedPackage (fullname, pkgsource, owner, check_hash, true))
+      if (validateCachedPackage (fullname, pkgsource, feedback, check_hash, true))
 	return 1;
       // If we get here, fullname was corrupt and deleted, but it
       // might have been cached.
@@ -134,7 +134,7 @@ check_for_cached (packagesource & pkgsource, HWND owner, bool mirror_mode,
       pkgsource.Canonical ();
     if (io_stream::exists(fullname))
 	{
-	  if (validateCachedPackage (fullname, pkgsource, owner, check_hash,
+	  if (validateCachedPackage (fullname, pkgsource, feedback, check_hash,
 				     true))
 	    return 1;
 	  // If we get here, fullname was corrupt and deleted, but it
@@ -151,7 +151,7 @@ download_one (packagesource & pkgsource, Feedback &feedback)
 {
   try
     {
-      if (check_for_cached (pkgsource, feedback.owner()))
+      if (check_for_cached (pkgsource, feedback))
         return 0;
     }
   catch (Exception * e)
@@ -190,7 +190,7 @@ download_one (packagesource & pkgsource, Feedback &feedback)
 		remove (local.c_str());
 	      rename ((local + ".tmp").c_str(), local.c_str());
 	      pkgsource.check_size_and_cache ("file://" + local);
-	      pkgsource.check_hash ();
+	      pkgsource.check_hash (feedback);
 	      Log (LOG_PLAIN) << "Downloaded " << local << endLog;
 	      success = 1;
 	      // FIXME: move the downloaded file to the 
@@ -277,6 +277,7 @@ do_download_thread (HINSTANCE h, HWND owner)
   int errors = 0;
   download_failures.clear ();
 
+  GuiFeedback feedback(owner);
   Progress.SetText1 (IDS_PROGRESS_CHECKING);
   Progress.SetText2 ("");
   Progress.SetText3 ("");
@@ -294,7 +295,7 @@ do_download_thread (HINSTANCE h, HWND owner)
 
       try
         {
-          if (!check_for_cached (*version.source(), owner))
+          if (!check_for_cached (*version.source(), feedback))
             total_download_bytes += version.source()->size;
         }
       catch (Exception * e)
@@ -308,7 +309,6 @@ do_download_thread (HINSTANCE h, HWND owner)
       Progress.SetBar2(std::distance(t.begin(), i) + 1, t.size());
     }
 
-  GuiFeedback feedback(owner);
   feedback.fetch_set_total_length(total_download_bytes);
 
   /* and do the download. FIXME: This here we assign a new name for the cached version
diff --git a/download.h b/download.h
index 9f4cb8e..3f65153 100644
--- a/download.h
+++ b/download.h
@@ -16,10 +16,10 @@
 #ifndef SETUP_DOWNLOAD_H
 #define SETUP_DOWNLOAD_H
 
-#include "win32.h"
+#include "Feedback.h"
 
 class packagesource;
-int check_for_cached (packagesource & pkgsource, HWND owner,
-		      bool mirror_mode = false, bool check_hash = true);
+int check_for_cached (packagesource & pkgsource, Feedback &feedback,
+                      bool mirror_mode = false, bool check_hash = true);
 
 #endif /* SETUP_DOWNLOAD_H */
diff --git a/gui/GuiFeedback.h b/gui/GuiFeedback.h
index 1dcd42f..7ac0c80 100644
--- a/gui/GuiFeedback.h
+++ b/gui/GuiFeedback.h
@@ -55,6 +55,11 @@ private:
   long long int total_download_bytes_sofar = 0;
   DWORD start_tics;
 
+  // hash checking
+public:
+  void hash_init (const char *hashalg, const std::string &url);
+  void hash_progress (int bytes, int total_bytes);
+
 public:
   // owner
   HWND owner () { return owner_window; }
diff --git a/gui/GuiHashCheckFeedback.cc b/gui/GuiHashCheckFeedback.cc
new file mode 100644
index 0000000..a0b4c57
--- /dev/null
+++ b/gui/GuiHashCheckFeedback.cc
@@ -0,0 +1,34 @@
+/*
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     A copy of the GNU General Public License can be found at
+ *     http://www.gnu.org/
+ *
+ */
+
+#include "gui/GuiFeedback.h"
+#include "resource.h"
+#include "threebar.h"
+#include "String++.h"
+
+extern ThreeBarProgressPage Progress;
+
+void
+GuiFeedback::hash_init(const char *hashalg, const std::string &shortname)
+{
+  std::wstring fmt = LoadStringW(IDS_PROGRESS_CHECKING_HASH);
+  std::wstring s = format(fmt, hashalg, shortname.c_str());
+  Progress.SetText1(s.c_str());
+  Progress.SetText4(IDS_PROGRESS_PROGRESS);
+  Progress.SetBar1(0);
+}
+
+void
+GuiFeedback::hash_progress(int bytes, int total_bytes)
+{
+  Progress.SetBar1(bytes, total_bytes);
+}
diff --git a/install.cc b/install.cc
index 001529b..578ff7f 100644
--- a/install.cc
+++ b/install.cc
@@ -62,6 +62,7 @@
 #include "threebar.h"
 #include "Exception.h"
 #include "processlist.h"
+#include "gui/GuiFeedback.h"
 
 extern ThreeBarProgressPage Progress;
 
@@ -805,6 +806,7 @@ static void
 do_install_thread (HINSTANCE h, HWND owner)
 {
   int i;
+  GuiFeedback feedback(owner);
 
   num_installs = 0, num_uninstalls = 0;
   rebootneeded = false;
@@ -870,7 +872,7 @@ do_install_thread (HINSTANCE h, HWND owner)
     {
       try
       {
-        (*version.source ()).check_hash ();
+        (*version.source ()).check_hash (feedback);
       }
       catch (Exception *e)
       {
diff --git a/package_db.cc b/package_db.cc
index 26ecc3c..244b6bb 100644
--- a/package_db.cc
+++ b/package_db.cc
@@ -752,7 +752,7 @@ packagedb::fixup_source_package_ids()
 }
 
 void
-packagedb::prep()
+packagedb::prep(Feedback &feedback)
 {
   /* make packagedb ready for use for chooser */
   if (prepped)
@@ -767,8 +767,8 @@ packagedb::prep()
 
   /* XXX: this needs to be broken out somewhere where it can do progress
      reporting, as it can take a long time... */
-  if (source == IDC_SOURCE_DOWNLOAD || source ==IDC_SOURCE_LOCALDIR)
-    packagemeta::ScanDownloadedFiles (MirrorOption);
+  if (source == IDC_SOURCE_DOWNLOAD || source == IDC_SOURCE_LOCALDIR)
+    packagemeta::ScanDownloadedFiles (MirrorOption, feedback);
 
   setExistence ();
   fillMissingCategory ();
diff --git a/package_db.h b/package_db.h
index 3886bf2..c3c2b05 100644
--- a/package_db.h
+++ b/package_db.h
@@ -23,6 +23,7 @@
 class packagemeta;
 class io_stream;
 class PackageSpecification;
+class Feedback;
 
 typedef enum {
   PackageDB_Install,
@@ -67,7 +68,7 @@ public:
   void init();
   /* 0 on success */
   int flush ();
-  void prep();
+  void prep(Feedback &);
   /* Set the database to a "no changes requested" state.  */
   void noChanges ();
 
diff --git a/package_meta.cc b/package_meta.cc
index 3daa970..0c5e2f5 100644
--- a/package_meta.cc
+++ b/package_meta.cc
@@ -833,7 +833,7 @@ packagemeta::logSelectionStatus() const
 
 /* scan for local copies of package */
 bool
-packagemeta::scan (const packageversion &pkg, bool mirror_mode)
+packagemeta::scan (const packageversion &pkg, bool mirror_mode, Feedback &feedback)
 {
   /* empty version */
   if (!pkg)
@@ -841,7 +841,7 @@ packagemeta::scan (const packageversion &pkg, bool mirror_mode)
 
   try
     {
-      if (!check_for_cached (*(pkg.source ()), NULL, mirror_mode, false)
+      if (!check_for_cached (*(pkg.source ()), feedback, mirror_mode, false)
           && ::source == IDC_SOURCE_LOCALDIR)
         return false;
     }
@@ -859,7 +859,7 @@ packagemeta::scan (const packageversion &pkg, bool mirror_mode)
 }
 
 void
-packagemeta::ScanDownloadedFiles (bool mirror_mode)
+packagemeta::ScanDownloadedFiles (bool mirror_mode, Feedback &feedback)
 {
   /* Look at every known package, in all the known mirror dirs,
    * and fill in the Cached attribute if it exists.
@@ -877,10 +877,10 @@ packagemeta::ScanDownloadedFiles (bool mirror_mode)
 			   && (*i != pkg.installed
 			       || pkg.installed == pkg.curr
 			       || pkg.installed == pkg.exp);
-	  bool accessible = scan (*i, lazy_scan);
+	  bool accessible = scan (*i, lazy_scan, feedback);
 	  packageversion foo = *i;
 	  packageversion pkgsrcver = foo.sourcePackage ();
-	  bool src_accessible = scan (pkgsrcver, lazy_scan);
+	  bool src_accessible = scan (pkgsrcver, lazy_scan, feedback);
 
 	  /* For local installs, if there is no src and no bin, the version
 	   * is unavailable
diff --git a/package_meta.h b/package_meta.h
index fee385b..896d848 100644
--- a/package_meta.h
+++ b/package_meta.h
@@ -19,6 +19,7 @@
 class SolvableVersion;
 typedef SolvableVersion packageversion;
 class packagemeta;
+class Feedback;
 
 #include <set>
 #include <vector>
@@ -34,7 +35,7 @@ typedef std::pair<const std::string, std::vector<packagemeta *> > Category;
 class packagemeta
 {
 public:
-  static void ScanDownloadedFiles (bool);
+  static void ScanDownloadedFiles (bool, Feedback&);
   packagemeta (packagemeta const &);
   packagemeta (const std::string& pkgname)
     : name (pkgname), user_picked (false),
@@ -162,7 +163,7 @@ protected:
 private:
   std::string trustLabel(packageversion const &) const;
   std::vector <Script> scripts_;
-  static bool scan (const packageversion &pkg, bool mirror_mode);
+  static bool scan (const packageversion &pkg, bool mirror_mode, Feedback &feedback);
   const packageversion * findVersion(std::string &version) const;
 
   _actions _action;
diff --git a/package_source.cc b/package_source.cc
index 2b5909b..a652a3b 100644
--- a/package_source.cc
+++ b/package_source.cc
@@ -21,13 +21,10 @@
 #include "sha2.h"
 #include "csu_util/MD5Sum.h"
 #include "LogFile.h"
-#include "threebar.h"
 #include "Exception.h"
 #include "filemanip.h"
 #include "io_stream.h"
-#include "resource.h"
-
-extern ThreeBarProgressPage Progress;
+#include "Feedback.h"
 
 site::site (const std::string& newkey) : key(newkey)
 {
@@ -65,19 +62,19 @@ packagesource::check_size_and_cache (const std::string fullname)
 }
 
 void
-packagesource::check_hash ()
+packagesource::check_hash (Feedback &feedback)
 {
   if (validated || cached.empty ())
     return;
 
   if (sha512_isSet)
     {
-      check_sha512 (cached);
+      check_sha512 (cached, feedback);
       validated = true;
     }
   else if (md5.isSet())
     {
-      check_md5 (cached);
+      check_md5 (cached, feedback);
       validated = true;
     }
   else
@@ -97,7 +94,7 @@ sha512_str (const unsigned char *in, char *buf)
 }
 
 void
-packagesource::check_sha512 (const std::string fullname) const
+packagesource::check_sha512 (const std::string fullname, Feedback &feedback) const
 {
   io_stream *thefile = io_stream::open (fullname, "rb", 0);
   if (!thefile)
@@ -112,19 +109,14 @@ packagesource::check_sha512 (const std::string fullname) const
   SHA512Init (&ctx);
 
   Log (LOG_BABBLE) << "Checking SHA512 for " << fullname << endLog;
-
-  std::wstring fmt = LoadStringW(IDS_PROGRESS_CHECKING_HASH);
-  std::wstring s = format(fmt, "SHA512", shortname.c_str());
-  Progress.SetText1 (s.c_str());
-  Progress.SetText4 (IDS_PROGRESS_PROGRESS);
-  Progress.SetBar1 (0);
+  feedback.hash_init("SHA512", shortname);
 
   unsigned char buffer[64 * 1024];
   ssize_t count;
   while ((count = thefile->read (buffer, sizeof (buffer))) > 0)
   {
     SHA512Update (&ctx, buffer, count);
-    Progress.SetBar1 (thefile->tell (), thefile->get_size ());
+    feedback.hash_progress(thefile->tell (), thefile->get_size ());
   }
   delete thefile;
   if (count < 0)
@@ -152,7 +144,7 @@ packagesource::check_sha512 (const std::string fullname) const
 }
 
 void
-packagesource::check_md5 (const std::string fullname) const
+packagesource::check_md5 (const std::string fullname, Feedback &feedback) const
 {
   io_stream *thefile = io_stream::open (fullname, "rb", 0);
   if (!thefile)
@@ -163,19 +155,14 @@ packagesource::check_md5 (const std::string fullname) const
   tempMD5.begin ();
 
   Log (LOG_BABBLE) << "Checking MD5 for " << fullname << endLog;
-
-  std::wstring fmt = LoadStringW(IDS_PROGRESS_CHECKING_HASH);
-  std::wstring s = format(fmt, "MD5", shortname);
-  Progress.SetText1 (s.c_str());
-  Progress.SetText4 (IDS_PROGRESS_PROGRESS);
-  Progress.SetBar1 (0);
+  feedback.hash_init("MD5", shortname);
 
   unsigned char buffer[64 * 1024];
   ssize_t count;
   while ((count = thefile->read (buffer, sizeof (buffer))) > 0)
     {
       tempMD5.append (buffer, count);
-      Progress.SetBar1 (thefile->tell (), thefile->get_size ());
+      feedback.hash_progress(thefile->tell (), thefile->get_size ());
     }
   delete thefile;
   if (count < 0)
diff --git a/package_source.h b/package_source.h
index fae46f7..663a603 100644
--- a/package_source.h
+++ b/package_source.h
@@ -26,6 +26,8 @@
 #include "csu_util/MD5Sum.h"
 #include <vector>
 
+class Feedback;
+
 class site
 {
 public:
@@ -79,7 +81,7 @@ public:
   MD5Sum md5;
   /* The next two functions throw exceptions on failure.  */
   void check_size_and_cache (const std::string fullname);
-  void check_hash ();
+  void check_hash (Feedback &feedback);
   typedef std::vector <site> sitestype;
   sitestype sites;
 
@@ -89,8 +91,8 @@ private:
   std::string shortname;
   std::string cached;
   bool validated;
-  void check_sha512 (const std::string fullname) const;
-  void check_md5 (const std::string fullname) const;
+  void check_sha512 (const std::string fullname, Feedback &feedback) const;
+  void check_md5 (const std::string fullname, Feedback &feedback) const;
 };
 
 #endif /* SETUP_PACKAGE_SOURCE_H */
-- 
2.43.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH setup 14/16] Push check_for_cached into package_source
  2024-03-08 18:34 [PATCH setup 00/16] Groundwork for a GUI-less installation tool Jon Turney
                   ` (12 preceding siblings ...)
  2024-03-08 18:34 ` [PATCH setup 13/16] Split out hash checking progress reporting Jon Turney
@ 2024-03-08 18:34 ` Jon Turney
  2024-03-08 18:34 ` [PATCH setup 15/16] Put various shared subcomponents into a convenience library Jon Turney
  2024-03-08 18:34 ` [PATCH setup 16/16] Add beginnings of a command line installation tool Jon Turney
  15 siblings, 0 replies; 17+ messages in thread
From: Jon Turney @ 2024-03-08 18:34 UTC (permalink / raw)
  To: cygwin-apps; +Cc: Jon Turney

This is kind of half-right. It helps make the package database code
self-contained (since that needs to use check_for_cached as part of
ScanDownloadedFiles), but also pulls apart the 'cache checking' and
'download file and put it in the cache'.  There's probably some scope
for an package_source interface for "where is the package cache download
location for this package from that site."
---
 download.cc       | 104 ++--------------------------------------------
 download.h        |   6 ---
 package_meta.cc   |   3 +-
 package_source.cc |  95 ++++++++++++++++++++++++++++++++++++++++++
 package_source.h  |   4 ++
 5 files changed, 103 insertions(+), 109 deletions(-)

diff --git a/download.cc b/download.cc
index fbe36e5..4aba83e 100644
--- a/download.cc
+++ b/download.cc
@@ -19,7 +19,7 @@
 #include "csu_util/rfc1738.h"
 
 #include "download.h"
-  
+
 #include "win32.h"
 
 #include <stdio.h>
@@ -28,7 +28,6 @@
 #include <vector>
 
 #include "resource.h"
-#include "msg.h"
 #include "dialog.h"
 #include "geturl.h"
 #include "state.h"
@@ -48,110 +47,13 @@
 
 extern ThreeBarProgressPage Progress;
 
-// Return true if selected checks pass, false if they don't and the
-// user chooses to delete the file; otherwise throw an exception.
-static bool
-validateCachedPackage (const std::string& fullname, packagesource & pkgsource,
-                       Feedback &feedback, bool check_hash, bool check_size)
-{
-  try
-    {
-      if (check_size)
-	pkgsource.check_size_and_cache (fullname);
-      if (check_hash)
-	pkgsource.check_hash (feedback);
-      return true;
-    }
-  catch (Exception *e)
-    {
-      pkgsource.set_cached ("");
-      const char *filename = fullname.c_str ();
-      if (strncmp (filename, "file://", 7) == 0)
-	filename += 7;
-      if (e->errNo() == APPERR_CORRUPT_PACKAGE
-	  && yesno (feedback.owner(), IDS_QUERY_CORRUPT, filename) == IDYES)
-	remove (filename);
-      else
-	throw e;
-    }
-  return false;
-}
-
-/* 0 if not cached; may throw exception if validation fails.
- */
-int
-check_for_cached (packagesource & pkgsource, Feedback &feedback,
-                  bool mirror_mode, bool check_hash)
-{
-  /* If the packagesource doesn't have a filename, it can't possibly be in the
-     cache */
-  if (!pkgsource.Canonical())
-    {
-      return 0;
-    }
-
-  /* Note that the cache dir is represented by a mirror site of file://local_dir */
-  std::string prefix = "file://" + local_dir + "/";
-  std::string fullname = prefix + pkgsource.Canonical();
-
-  if (mirror_mode)
-    {
-      /* Just assume correctness of mirror. */
-      if (!pkgsource.Cached())
-	pkgsource.set_cached (fullname);
-      return 1;
-    }
-
-  // Already found one, which we can assume to have the right size.
-  if (pkgsource.Cached())
-    {
-      if (validateCachedPackage (pkgsource.Cached(), pkgsource, feedback,
-				 check_hash, false))
-	return 1;
-      // If we get here, pkgsource.Cached() was corrupt and deleted.
-      pkgsource.set_cached ("");
-    }
-
-  /*
-     1) is there a legacy version in the cache dir available.
-  */
-  if (io_stream::exists (fullname))
-    {
-      if (validateCachedPackage (fullname, pkgsource, feedback, check_hash, true))
-	return 1;
-      // If we get here, fullname was corrupt and deleted, but it
-      // might have been cached.
-      pkgsource.set_cached ("");
-    }
-
-  /*
-     2) is there a version from one of the selected mirror sites available ?
-  */
-  for (packagesource::sitestype::const_iterator n = pkgsource.sites.begin();
-       n != pkgsource.sites.end(); ++n)
-  {
-    std::string fullname = prefix + rfc1738_escape_part (n->key) + "/" +
-      pkgsource.Canonical ();
-    if (io_stream::exists(fullname))
-	{
-	  if (validateCachedPackage (fullname, pkgsource, feedback, check_hash,
-				     true))
-	    return 1;
-	  // If we get here, fullname was corrupt and deleted, but it
-	  // might have been cached.
-	  pkgsource.set_cached ("");
-	}
-  }
-  return 0;
-}
-
 /* download a file from a mirror site to the local cache. */
 static int
 download_one (packagesource & pkgsource, Feedback &feedback)
 {
   try
     {
-      if (check_for_cached (pkgsource, feedback))
+      if (pkgsource.check_for_cached(feedback))
         return 0;
     }
   catch (Exception * e)
@@ -295,7 +197,7 @@ do_download_thread (HINSTANCE h, HWND owner)
 
       try
         {
-          if (!check_for_cached (*version.source(), feedback))
+          if (!(version.source()->check_for_cached(feedback)))
             total_download_bytes += version.source()->size;
         }
       catch (Exception * e)
diff --git a/download.h b/download.h
index 3f65153..e887c92 100644
--- a/download.h
+++ b/download.h
@@ -16,10 +16,4 @@
 #ifndef SETUP_DOWNLOAD_H
 #define SETUP_DOWNLOAD_H
 
-#include "Feedback.h"
-
-class packagesource;
-int check_for_cached (packagesource & pkgsource, Feedback &feedback,
-                      bool mirror_mode = false, bool check_hash = true);
-
 #endif /* SETUP_DOWNLOAD_H */
diff --git a/package_meta.cc b/package_meta.cc
index 0c5e2f5..4baea34 100644
--- a/package_meta.cc
+++ b/package_meta.cc
@@ -41,7 +41,6 @@
 #include <functional>
 
 #include "Generic.h"
-#include "download.h"
 #include "Exception.h"
 #include "resource.h"
 
@@ -841,7 +840,7 @@ packagemeta::scan (const packageversion &pkg, bool mirror_mode, Feedback &feedba
 
   try
     {
-      if (!check_for_cached (*(pkg.source ()), feedback, mirror_mode, false)
+      if (!pkg.source()->check_for_cached(feedback, mirror_mode, false)
           && ::source == IDC_SOURCE_LOCALDIR)
         return false;
     }
diff --git a/package_source.cc b/package_source.cc
index a652a3b..bc90158 100644
--- a/package_source.cc
+++ b/package_source.cc
@@ -25,6 +25,9 @@
 #include "filemanip.h"
 #include "io_stream.h"
 #include "Feedback.h"
+#include "csu_util/rfc1738.h"
+#include "resource.h"
+#include "state.h"
 
 site::site (const std::string& newkey) : key(newkey)
 {
@@ -185,3 +188,95 @@ packagesource::check_md5 (const std::string fullname, Feedback &feedback) const
   Log (LOG_BABBLE) << "MD5 verified OK: " << fullname << " "
     << md5.str() << endLog;
 }
+
+// Return true if selected checks pass, false if they don't and the
+// user chooses to delete the file; otherwise throw an exception.
+static bool
+validateCachedPackage (const std::string& fullname, packagesource &pkgsource,
+                       Feedback &feedback, bool check_hash, bool check_size)
+{
+  try
+    {
+      if (check_size)
+        pkgsource.check_size_and_cache (fullname);
+      if (check_hash)
+        pkgsource.check_hash (feedback);
+      return true;
+    }
+  catch (Exception *e)
+    {
+      pkgsource.set_cached ("");
+      const char *filename = fullname.c_str ();
+      if (strncmp (filename, "file://", 7) == 0)
+        filename += 7;
+      if (e->errNo() == APPERR_CORRUPT_PACKAGE
+          && yesno (feedback.owner(), IDS_QUERY_CORRUPT, filename) == IDYES)
+        remove (filename);
+      else
+        throw e;
+    }
+  return false;
+}
+
+int
+packagesource::check_for_cached (Feedback &feedback, bool mirror_mode,
+                                 bool check_hash)
+{
+  /* If the packagesource doesn't have a filename, it can't possibly be in the
+     cache */
+  if (!Canonical())
+    {
+      return 0;
+    }
+
+  /* Note that the cache dir is represented by a mirror site of file://local_dir */
+  std::string prefix = "file://" + local_dir + "/";
+  std::string fullname = prefix + Canonical();
+
+  if (mirror_mode)
+    {
+      /* Just assume correctness of mirror. */
+      if (!Cached())
+        set_cached (fullname);
+      return 1;
+    }
+
+  // Already found one, which we can assume to have the right size.
+  if (Cached())
+    {
+      if (validateCachedPackage (Cached(), *this, feedback, check_hash, false))
+        return 1;
+      // If we get here, this.Cached() was corrupt and deleted.
+      set_cached ("");
+    }
+
+  /*
+     1) is there a legacy version in the cache dir available.
+  */
+  if (io_stream::exists (fullname))
+    {
+      if (validateCachedPackage (fullname, *this, feedback, check_hash, true))
+        return 1;
+      // If we get here, fullname was corrupt and deleted, but it
+      // might have been cached.
+      set_cached ("");
+    }
+
+  /*
+     2) is there a version from one of the selected mirror sites available ?
+  */
+  for (packagesource::sitestype::const_iterator n = sites.begin();
+       n != sites.end(); ++n)
+  {
+    std::string fullname = prefix + rfc1738_escape_part (n->key) + "/" + Canonical ();
+    if (io_stream::exists(fullname))
+        {
+          if (validateCachedPackage (fullname, *this, feedback, check_hash, true))
+            return 1;
+          // If we get here, fullname was corrupt and deleted, but it
+          // might have been cached.
+          set_cached ("");
+        }
+  }
+  return 0;
+}
diff --git a/package_source.h b/package_source.h
index 663a603..52efc4b 100644
--- a/package_source.h
+++ b/package_source.h
@@ -85,6 +85,10 @@ public:
   typedef std::vector <site> sitestype;
   sitestype sites;
 
+  /* returns 0 if not cached; may throw exception if validation fails. */
+  int check_for_cached (Feedback &feedback, bool mirror_mode = false,
+                        bool check_hash = true);
+
 private:
   std::string canonical;
   /* For progress reporting.  */
-- 
2.43.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH setup 15/16] Put various shared subcomponents into a convenience library
  2024-03-08 18:34 [PATCH setup 00/16] Groundwork for a GUI-less installation tool Jon Turney
                   ` (13 preceding siblings ...)
  2024-03-08 18:34 ` [PATCH setup 14/16] Push check_for_cached into package_source Jon Turney
@ 2024-03-08 18:34 ` Jon Turney
  2024-03-08 18:34 ` [PATCH setup 16/16] Add beginnings of a command line installation tool Jon Turney
  15 siblings, 0 replies; 17+ messages in thread
From: Jon Turney @ 2024-03-08 18:34 UTC (permalink / raw)
  To: cygwin-apps; +Cc: Jon Turney

* logging, settings, netio, iostream, decompressors, packagedb,
csu_util, hashes, signature checking, URL fetching, Exception class, ini
fetching and parsing, global state, version
---
 Makefile.am | 246 +++++++++++++++++++++++++++-------------------------
 1 file changed, 126 insertions(+), 120 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index def20a4..6ae5dd6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -37,6 +37,9 @@ iniparse_CXXFLAGS:=-Wno-free-nonheap-object
 
 noinst_PROGRAMS = @SETUP@$(EXEEXT) inilint
 
+noinst_LTLIBRARIES = \
+	libsetupcore.la
+
 EXTRA_DIST = \
 	CHANGES \
 	CONTRIBUTORS \
@@ -59,35 +62,15 @@ BUILT_SOURCES = \
 CLEANFILES = setup_version.c
 
 inilint_LDADD = \
-	libgetopt++/libgetopt++.la \
-	-lntdll -luuid
+	libsetupcore.la \
+	libgetopt++/libgetopt++.la
 
 inilint_SOURCES = \
-	filemanip.cc \
-	filemanip.h \
 	cli/CliParseFeedback.cc \
 	cli/CliGetUrlFeedback.cc \
 	cli/CliHashCheckFeedback.cc \
 	cli/CliFeedback.h \
-	LogSingleton.cc \
-	LogSingleton.h \
-	IniDBBuilder.h \
-	inilintmain.cc \
-	inilex.ll \
-	iniparse.yy \
-	io_stream.cc \
-	io_stream.h \
-	io_stream_file.cc \
-	io_stream_file.h \
-	mkdir.cc \
-	mkdir.h \
-	mklink2.cc \
-	mklink2.h \
-	PackageTrust.h \
-	String++.cc \
-	String++.h \
-	win32.cc \
-	win32.h
+	inilintmain.cc
 
 # Do not link directly with wininet, as it's vulnerable to sideloading/dll
 # hijacking. Instead we make and link with a delay-loading stub lib, so it's
@@ -116,19 +99,134 @@ WININET=wininet-delaylib.a
 EXTRA_@SETUP@_DEPENDENCIES=wininet-delaylib.a
 endif
 
-@SETUP@_LDADD = \
-	libgetopt++/libgetopt++.la \
+libsetupcore_la_SOURCES = \
+	ConnectionSetting.cc \
+	ConnectionSetting.h \
+	Exception.cc \
+	Exception.h \
+	IniDBBuilder.h \
+	IniDBBuilderPackage.cc \
+	IniDBBuilderPackage.h \
+	KeysSetting.cc \
+	KeysSetting.h \
+	LogFile.cc \
+	LogFile.h \
+	LogSingleton.cc \
+	LogSingleton.h \
+	PackageSpecification.cc \
+	PackageSpecification.h \
+	PackageTrust.h \
+	SiteSetting.cc \
+	SiteSetting.h \
+	SourceSetting.cc \
+	SourceSetting.h \
+	String++.cc \
+	String++.h \
+	UserSettings.cc \
+	UserSettings.h \
+	compactos.cc \
+	compactos.h \
+	compress.cc \
+	compress.h \
+	compress_bz.cc \
+	compress_bz.h \
+	compress_gz.cc \
+	compress_gz.h \
+	compress_xz.cc \
+	compress_xz.h \
+	compress_zstd.cc \
+	compress_zstd.h \
+	crypto.cc \
+	crypto.h \
+	csu_util/MD5Sum.cc \
+	csu_util/MD5Sum.h \
+	csu_util/rfc1738.cc \
+	csu_util/rfc1738.h \
+	csu_util/version_compare.cc \
+	csu_util/version_compare.h \
+	filemanip.cc \
+	filemanip.h \
+	geturl.cc \
+	geturl.h \
+	gpg-packet.cc \
+	gpg-packet.h \
+	ini.cc \
+	ini.h \
+	inilex.ll \
+	iniparse.yy \
+	io_stream.cc \
+	io_stream.h \
+	io_stream_memory.cc \
+	io_stream_memory.h \
+	libsolv.cc \
+	libsolv.h \
+	mkdir.cc \
+	mkdir.h \
+	mklink2.cc \
+	mklink2.h \
+	mount.cc \
+	netio.cc \
+	netio.h \
+	nio-ie5.cc \
+	nio-ie5.h \
+	package_db.cc \
+	package_db.h \
+	package_depends.cc \
+	package_depends.h \
+	package_meta.cc \
+	package_meta.h \
+	package_source.cc \
+	package_source.h \
+	package_version.h \
+	setup_version.c \
+	setup_version.h \
+	sha2.c \
+	sha2.h \
+	state.cc \
+	state.h \
+	win32.cc \
+	win32.h
+
+# warning: always link with mingwex (which gcc specs will cause us to link with
+# anyhow) before ntdll, to ensure we don't link with CRT functions (avaliable in
+# some versions of) the ntdll import lib which aren't available on XP.
+libsetupcore_la_LDFLAGS = \
 	$(LIBGCRYPT_LIBS) \
 	$(ZSTD_LIBS) \
 	$(LZMA_LIBS) \
 	$(BZ2_LIBS) \
 	$(ZLIB_LIBS) \
-	$(LIBSOLV_LIBS) -lregex \
+	$(LIBSOLV_LIBS) \
+	-lregex \
 	-lmingwex \
-	-lshlwapi -lcomctl32 -lole32 -lpsapi -luuid -lntdll $(WININET) -lws2_32 \
+	-lshlwapi \
+	-luuid \
+	-lntdll \
+	-lws2_32
+
+# because of a totally unnecessary "private registration" by static
+# constructors, these sources are completely unsuitable for putting in a library
+# (as the providers are not referenced and so aren't included in the final
+# link), so everything with needs them must include these objects
+IOSTREAM_PROVIDERS = \
+	io_stream_cygfile.cc \
+	io_stream_cygfile.h \
+	io_stream_file.cc \
+	io_stream_file.h
+
+@SETUP@_LDADD = \
+	libsetupcore.la \
+	libgetopt++/libgetopt++.la \
+	$(WININET) \
+	-lcomctl32 \
+	-lole32 \
+	-lpsapi \
 	-lmingw32 -lssp
+
 @SETUP@_LDFLAGS = -mwindows -Wc,-static -static-libtool-libs
+
 @SETUP@_SOURCES = \
+	$(IOSTREAM_PROVIDERS) \
 	actionlist.h \
 	AntiVirus.cc \
 	AntiVirus.h \
@@ -139,26 +237,10 @@ endif
 	archive_tar_file.cc \
 	choose.cc \
 	choose.h \
-	compactos.cc \
-	compactos.h \
-	compress.cc \
-	compress.h \
-	compress_bz.cc \
-	compress_bz.h \
-	compress_gz.cc \
-	compress_gz.h \
-	compress_xz.cc \
-	compress_xz.h \
-	compress_zstd.cc \
-	compress_zstd.h \
 	confirm.cc \
 	confirm.h \
-	ConnectionSetting.cc \
-	ConnectionSetting.h \
 	ControlAdjuster.cc \
 	ControlAdjuster.h \
-	crypto.cc \
-	crypto.h \
 	cyg-pubkey.h \
 	desktop.cc \
 	desktop.h \
@@ -168,83 +250,29 @@ endif
 	diskfull.h \
 	download.cc \
 	download.h \
-	Exception.cc \
-	Exception.h \
 	find.cc \
 	find.h \
 	FindVisitor.cc \
 	FindVisitor.h \
-	filemanip.cc \
-	filemanip.h \
 	fromcwd.cc \
 	Generic.h \
-	geturl.cc \
-	geturl.h \
-	gpg-packet.cc \
-	gpg-packet.h \
 	gui/GuiParseFeedback.cc \
 	gui/GuiGetNetAuth.cc \
 	gui/GuiGetNetAuth.h \
 	gui/GuiGetUrlFeedback.cc \
 	gui/GuiFeedback.h \
 	gui/GuiHashCheckFeedback.cc \
-	ini.cc \
-	ini.h \
-	IniDBBuilder.h \
-	IniDBBuilderPackage.cc \
-	IniDBBuilderPackage.h \
-	inilex.ll \
-	iniparse.yy \
 	Feedback.h \
 	install.cc \
-	io_stream.cc \
-	io_stream.h \
-	io_stream_cygfile.cc \
-	io_stream_cygfile.h \
-	io_stream_file.cc \
-	io_stream_file.h \
-	io_stream_memory.cc \
-	io_stream_memory.h \
-	IOStreamProvider.h \
-	KeysSetting.cc \
-	KeysSetting.h \
-	libsolv.cc \
-	libsolv.h \
 	ListView.cc \
 	ListView.h \
 	localdir.cc \
 	localdir.h \
-	LogFile.cc \
-	LogFile.h \
-	LogSingleton.cc \
-	LogSingleton.h \
 	main.cc \
-	mkdir.cc \
-	mkdir.h \
-	mklink2.cc \
-	mklink2.h \
-	mount.cc \
-	mount.h \
 	msg.cc \
 	msg.h \
 	net.cc \
 	net.h \
-	netio.cc \
-	netio.h \
-	nio-ie5.cc \
-	nio-ie5.h \
-	package_db.cc \
-	package_db.h \
-	package_depends.h \
-	package_depends.cc \
-	package_meta.cc \
-	package_meta.h \
-	package_source.cc \
-	package_source.h \
-	package_version.h \
-	PackageSpecification.cc \
-	PackageSpecification.h \
-	PackageTrust.h \
 	PickCategoryLine.cc \
 	PickCategoryLine.h \
 	PickPackageLine.cc \
@@ -269,38 +297,16 @@ endif
 	root.h \
 	script.cc \
 	script.h \
-	setup_version.h \
-	setup_version.c \
-	sha2.h \
-	sha2.c \
 	gui/SitePage.cc \
 	gui/SitePage.h \
-	SiteSetting.cc \
-	SiteSetting.h \
 	source.cc \
 	source.h \
-	SourceSetting.cc \
-	SourceSetting.h \
 	splash.cc \
 	splash.h \
-	state.cc \
-	state.h \
-	String++.cc \
-	String++.h \
 	threebar.cc \
 	threebar.h \
-	UserSettings.cc \
-	UserSettings.h \
-	win32.cc \
-	win32.h \
 	window.cc \
-	window.h \
-	csu_util/MD5Sum.cc \
-	csu_util/MD5Sum.h \
-	csu_util/rfc1738.cc \
-	csu_util/rfc1738.h \
-	csu_util/version_compare.cc \
-	csu_util/version_compare.h
+	window.h
 
 GITVER := $(shell cd $(srcdir) && git describe --match release_\* --abbrev=6 --dirty || echo "N/A")
 VER := $(subst release_,,$(GITVER))
-- 
2.43.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH setup 16/16] Add beginnings of a command line installation tool
  2024-03-08 18:34 [PATCH setup 00/16] Groundwork for a GUI-less installation tool Jon Turney
                   ` (14 preceding siblings ...)
  2024-03-08 18:34 ` [PATCH setup 15/16] Put various shared subcomponents into a convenience library Jon Turney
@ 2024-03-08 18:34 ` Jon Turney
  15 siblings, 0 replies; 17+ messages in thread
From: Jon Turney @ 2024-03-08 18:34 UTC (permalink / raw)
  To: cygwin-apps; +Cc: Jon Turney

At the moment, all this can do is retrieve setup.ini from a selected
mirror and parse it.
---
 Makefile.am    |  22 +++++-
 cli/cyclops.cc | 186 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 207 insertions(+), 1 deletion(-)
 create mode 100644 cli/cyclops.cc

diff --git a/Makefile.am b/Makefile.am
index 6ae5dd6..5813e1a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -35,7 +35,10 @@ AM_CPPFLAGS = -D__USE_MINGW_ANSI_STDIO=1 -D_FILE_OFFSET_BITS=64 -DLZMA_API_STATI
 inilex_CXXFLAGS:=-Wno-sign-compare
 iniparse_CXXFLAGS:=-Wno-free-nonheap-object
 
-noinst_PROGRAMS = @SETUP@$(EXEEXT) inilint
+noinst_PROGRAMS = \
+	@SETUP@$(EXEEXT) \
+	inilint \
+	cyclops
 
 noinst_LTLIBRARIES = \
 	libsetupcore.la
@@ -214,6 +217,23 @@ IOSTREAM_PROVIDERS = \
 	io_stream_file.cc \
 	io_stream_file.h
 
+cyclops_SOURCES = \
+	$(IOSTREAM_PROVIDERS) \
+	cli/CliParseFeedback.cc \
+	cli/CliGetNetAuth.cc \
+	cli/CliGetUrlFeedback.cc \
+	cli/CliHashCheckFeedback.cc \
+	cli/CliFeedback.h \
+	cli/cyclops.cc \
+	res.rc
+
+cyclops_LDADD = \
+	libsetupcore.la \
+	libgetopt++/libgetopt++.la \
+	$(WININET)
+
+cyclops_LDFLAGS = -mconsole -Wc,-static -static-libtool-libs
+
 @SETUP@_LDADD = \
 	libsetupcore.la \
 	libgetopt++/libgetopt++.la \
diff --git a/cli/cyclops.cc b/cli/cyclops.cc
new file mode 100644
index 0000000..549b65a
--- /dev/null
+++ b/cli/cyclops.cc
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2020 Jon Turney
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     A copy of the GNU General Public License can be found at
+ *     http://www.gnu.org/
+ *
+ */
+
+/*
+ * The one-eyed hippo sees all!
+ */
+
+#include "CliGetNetAuth.h"
+#include "CliFeedback.h"
+#include "ini.h"
+#include "LogFile.h"
+#include "resource.h"
+#include "setup_version.h"
+#include "state.h"
+
+#include "ConnectionSetting.h"
+#include "KeysSetting.h"
+#include "SiteSetting.h"
+#include "UserSettings.h"
+#include "netio.h"
+
+#include "getopt++/GetOption.h"
+#include "getopt++/BoolOption.h"
+
+BoolOption UnsupportedOption (false, '\0', "allow-unsupported-windows", IDS_HELPTEXT_ALLOW_UNSUPPORTED_WINDOWS);
+static BoolOption HelpOption (false, 'h', "help", IDS_HELPTEXT_HELP);
+
+static void
+main_cli ()
+{
+  // installation RootDir is already established by read_mounts()
+  ConnectionSetting ConnectionSettings;
+  ExtraKeysSetting ExtraKeys;
+  SiteSetting ChosenSites;
+
+  // check windows version and abort if too low unless UnsupportedOption
+
+  // announce myself
+  std::cout << "cyclops " << setup_version << std::endl;
+
+  // mode of operation
+  // XXX: probably only support download and install mode
+  source = IDC_SOURCE_NETINST;
+
+  // XXX: local package cache dir (from options or setup.rc)
+  // (fetched setp.ini is stored here)
+  char cwd[MAX_PATH];
+  GetCurrentDirectory (MAX_PATH, cwd);
+  local_dir = std::string (cwd);
+
+  // proxy
+
+  // interactive network auth getter
+  NetIO::auth_getter = new CliGetNetAuth();
+
+  // mirror site
+
+  // fetch and parse ini file(s)
+  CliFeedback feedback;
+  bool succeeded = do_ini_thread(feedback);
+  Log (LOG_PLAIN) << "do_ini_thread: " << succeeded << endLog;
+}
+
+static void
+main_wrap ()
+{
+  UserSettings Settings;
+  Settings.load (std::string());
+  main_cli ();
+  Settings.save (); // Clean exit. save user options.
+}
+
+int
+main (int argc, char **argv)
+{
+  LogSingleton::SetInstance (*LogFile::createLogFile ());
+
+  bool help_option = false;
+  bool invalid_option = false;
+
+  if (!GetOption::GetInstance ().Process (argc, argv, NULL))
+      help_option = invalid_option = true;
+    else if (HelpOption)
+      help_option = true;
+
+  if (help_option)
+    {
+      if (invalid_option)
+        Log (LOG_PLAIN) << "\n" << LoadStringUtf8(IDS_HELPTEXT_ERROR) << "\n" << endLog;
+
+      Log (LOG_PLAIN) << "\n" << LoadStringUtf8(IDS_HELPTEXT_HEADER) << "\n" << endLog;
+      GetOption::GetInstance ().ParameterUsage (Log (LOG_PLAIN), LoadStringUtf8);
+
+      Logger ().exit (invalid_option ? 1 : 0, false);
+      return 1;
+    }
+
+  LogSingleton::SetInstance (*LogFile::createLogFile ());
+
+  main_wrap();
+
+  return 0;
+}
+
+/* --- */
+
+#include <windows.h>
+#include "String++.h"
+
+int
+mbox (HWND owner, const char *buf, const char *name, int type)
+{
+  Log (LOG_PLAIN) << "mbox " << name << ": " << buf << endLog;
+
+  // XXX: unattended_result?
+  return IDOK;
+}
+
+int
+mbox(HWND owner, unsigned int format_id, int mb_type, ...)
+{
+  std::wstring fmt = LoadStringWEx(format_id, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
+  if (fmt.empty())
+    fmt = L"Internal error: format string resource not found";
+
+  va_list args;
+  va_start(args, mb_type);
+  std::wstring buf = vformat(fmt, args);
+  va_end(args);
+
+  // write unlocalized to log as UTF8
+  Log (LOG_PLAIN) << "mbox " << ": " << wstring_to_string(buf) << endLog;
+
+  // XXX: unattended_result?
+  return IDOK;
+}
+
+static int
+mbox (HWND owner, const char *name, int type, int id, va_list args)
+{
+  char buf[1000], fmt[1000];
+
+  if (LoadString (GetModuleHandle(NULL), id, fmt, sizeof (fmt)) <= 0)
+    ExitProcess (0);
+
+  vsnprintf (buf, 1000, fmt, args);
+  return mbox(owner, buf, name, type);
+}
+
+void
+note (HWND owner, int id, ...)
+{
+  va_list args;
+  va_start (args, id);
+  mbox (owner, "note", MB_OK, id, args);
+}
+
+void
+fatal (HWND owner, int id, ...)
+{
+  va_list args;
+  va_start (args, id);
+  mbox (owner, "fatal", MB_OK, id, args);
+  Logger ().exit (1);
+}
+
+int
+yesno (HWND owner, int id, ...)
+{
+  va_list args;
+  va_start (args, id);
+  mbox (owner, "yesno", MB_YESNO, id, args);
+  Log (LOG_PLAIN) << "Y/N" << endLog;
+  // XXX: yesno response!!!
+  return IDYES;
+}
-- 
2.43.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2024-03-08 18:36 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-08 18:34 [PATCH setup 00/16] Groundwork for a GUI-less installation tool Jon Turney
2024-03-08 18:34 ` [PATCH setup 01/16] Drop forward declaration of non-existent class IniState Jon Turney
2024-03-08 18:34 ` [PATCH setup 02/16] Move setup_exts[] to the only place it's used Jon Turney
2024-03-08 18:34 ` [PATCH setup 03/16] Split GuiParseFeedback out from ini fetcher Jon Turney
2024-03-08 18:34 ` [PATCH setup 04/16] Split out site into SiteSettings and SitePage Jon Turney
2024-03-08 18:34 ` [PATCH setup 05/16] Don't call Antivirus::AtExit() directly from Logger::exit() Jon Turney
2024-03-08 18:34 ` [PATCH setup 06/16] Simplify invocation of UserSettings::open_settings() Jon Turney
2024-03-08 18:34 ` [PATCH setup 07/16] Split out URL fetching progress reporting Jon Turney
2024-03-08 18:34 ` [PATCH setup 08/16] Instantiate found_ini_list in ini.cc Jon Turney
2024-03-08 18:34 ` [PATCH setup 09/16] Move is_64bit to state Jon Turney
2024-03-08 18:34 ` [PATCH setup 10/16] Move setup.ini pathame components to ini.cc Jon Turney
2024-03-08 18:34 ` [PATCH setup 11/16] Drop hinstance global Jon Turney
2024-03-08 18:34 ` [PATCH setup 12/16] Spit out GetNetAuth from NetIO Jon Turney
2024-03-08 18:34 ` [PATCH setup 13/16] Split out hash checking progress reporting Jon Turney
2024-03-08 18:34 ` [PATCH setup 14/16] Push check_for_cached into package_source Jon Turney
2024-03-08 18:34 ` [PATCH setup 15/16] Put various shared subcomponents into a convenience library Jon Turney
2024-03-08 18:34 ` [PATCH setup 16/16] Add beginnings of a command line installation tool Jon Turney

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).