Initial revision
[chise/xemacs-chise.git.1] / netinstall / uninstall.cc
diff --git a/netinstall/uninstall.cc b/netinstall/uninstall.cc
new file mode 100644 (file)
index 0000000..6117b3e
--- /dev/null
@@ -0,0 +1,326 @@
+/*
+ * 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>
+ *
+ */
+
+/* The purpose of this file is to intall all the packages selected in
+   the install list (in ini.h).  Note that we use a separate thread to
+   maintain the progress dialog, so we avoid the complexity of
+   handling two tasks in one thread.  We also create or update all the
+   files in /etc/setup and create the mount points. */
+
+#include <io.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#ifndef WIN32_NATIVE
+#include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <zlib.h>
+
+#include "win32.h"
+#include "commctrl.h"
+
+#include "resource.h"
+#include "ini.h"
+#include "dialog.h"
+#include "concat.h"
+#include "geturl.h"
+#include "mkdir.h"
+#include "state.h"
+#include "tar.h"
+#include "diskfull.h"
+#include "msg.h"
+#include "regedit.h"
+#include "reginfo.h"
+#include "log.h"
+#include "hash.h"
+
+#include "port.h"
+
+#define XM_DONE (WM_USER + 101)
+
+static HWND unins_dialog = 0;
+static HWND unins_action = 0;
+static HWND unins_pkgname = 0;
+static HWND unins_filename = 0;
+static HWND unins_pprogress = 0;
+static HWND unins_iprogress = 0;
+static HWND unins_diskfull = 0;
+static HANDLE init_event;
+
+static int package_bytes = 0;
+static int uninstall_started = 0;
+
+extern char * map_filename (char *fn, int type);
+void remove_desktop_setup ();
+static void start_uninstall ();
+extern char* find_xemacs_exe_name();
+
+char *
+base (char *s);
+
+static BOOL
+dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
+{
+  switch (id)
+    {
+    case IDCANCEL:
+      exit_setup (1);
+    case IDOK:
+      if (uninstall_started == 0) {
+       uninstall_started = 1;
+       start_uninstall();
+      }
+      else
+       exit_setup(0);
+      break;
+    }
+  return FALSE;
+}
+
+static BOOL CALLBACK
+dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  switch (message)
+    {
+    case WM_INITDIALOG:
+      unins_dialog = h;
+      unins_action = GetDlgItem (h, IDC_UNINS_ACTION);
+      unins_pkgname = GetDlgItem (h, IDC_UNINS_PKG);
+      unins_filename = GetDlgItem (h, IDC_UNINS_FILE);
+      unins_pprogress = GetDlgItem (h, IDC_UNINS_PPROGRESS);
+      unins_iprogress = GetDlgItem (h, IDC_UNINS_IPROGRESS);
+      unins_diskfull = GetDlgItem (h, IDC_UNINS_DISKFULL);
+      SendMessage (unins_pprogress, PBM_SETRANGE, 0, MAKELPARAM (0, 100));
+      SendMessage (unins_iprogress, PBM_SETRANGE, 0, MAKELPARAM (0, 100));
+      SendMessage (unins_diskfull, PBM_SETRANGE, 0, MAKELPARAM (0, 100));
+      SetWindowText (unins_pkgname, "");
+      SetWindowText (unins_filename, "");
+      SendMessage (unins_pprogress, PBM_SETPOS, (WPARAM) 0, 0);
+      SendMessage (unins_iprogress, PBM_SETPOS, (WPARAM) 0, 0);
+      SendMessage (unins_diskfull, PBM_SETPOS, (WPARAM) 0, 0);
+      return FALSE;
+
+    case XM_DONE:
+      {
+       SetWindowText (GetDlgItem (h, IDOK), "Ok");
+       LONG style = GetWindowLong (GetDlgItem (h, IDCANCEL),
+                                   GWL_STYLE);
+       SetWindowLong (GetDlgItem (h, IDCANCEL),
+                      GWL_STYLE, style & WS_DISABLED);
+      }
+      return FALSE;
+      
+    case WM_COMMAND:
+      return HANDLE_WM_COMMAND (h, wParam, lParam, dialog_cmd);
+    }
+  return DefWindowProc (h, message, wParam, lParam);
+}
+
+static DWORD WINAPI uninstall_all (void *);
+
+static void
+start_uninstall ()
+{
+  DWORD tid;
+  HANDLE thread;
+  init_event = CreateEvent (0, 0, 0, 0);
+  thread = CreateThread (0, 0, uninstall_all, 0, 0, &tid);
+  WaitForSingleObject (init_event, 10000);
+  CloseHandle (init_event);
+}
+
+static void
+progress (int bytes, int num)
+{
+  int perc;
+  if (package_bytes > 100)
+    {
+      perc = (bytes * 100) / package_bytes;
+      SendMessage (unins_pprogress, PBM_SETPOS, (WPARAM) perc, 0);
+    }
+
+  if (npackages > 0)
+    {
+      perc = (num * 100) / npackages;
+      SendMessage (unins_iprogress, PBM_SETPOS, (WPARAM) perc, 0);
+    }
+}
+
+static int num_installs, num_uninstalls;
+
+static void
+uninstall_one (char *name, int type, int num)
+{
+  hash dirs;
+  char line[_MAX_PATH];
+  char* fname = (type == TY_GENERIC ? 
+                concat (root_dir, XEMACS_PACKAGE_DIR, "pkginfo/MANIFEST.",
+                        name,  0) :
+                concat (root_dir, XEMACS_SETUP_DIR, "MANIFEST.", name,  0));
+
+  FILE* lst = fopen (fname, "rb");
+  int pos = 0;
+
+  if (lst)
+    {
+      fseek (lst, 0, SEEK_END);
+      package_bytes = ftell (lst);
+      fseek (lst, 0, SEEK_SET);
+  
+      SetWindowText (unins_pkgname, name);
+      SetWindowText (unins_action, "Uninstalling...");
+      log (0, "uninstalling %s", name);
+
+      while (fgets (line, sizeof (line), lst))
+       {
+         progress (pos, num);
+         pos += strlen(line);
+         if (line[strlen(line)-1] == '\n')
+           line[strlen(line)-1] = 0;
+
+         dirs.add_subdirs (line);
+
+         char *d = map_filename (line, type);
+         DWORD dw = GetFileAttributes (d);
+         if (dw != 0xffffffff && !(dw & FILE_ATTRIBUTE_DIRECTORY))
+           {
+             log (LOG_BABBLE, "unlink %s", d);
+             DeleteFile (d);
+           }
+       }
+      fclose (lst);
+      remove (fname);
+
+      dirs.reverse_sort ();
+      char *subdir = 0;
+      while ((subdir = dirs.enumerate (subdir)) != 0)
+       {
+         char *d = map_filename (subdir, type);
+         if (RemoveDirectory (d))
+           log (LOG_BABBLE, "rmdir %s", d);
+       }
+      num_uninstalls ++;
+    }
+}
+
+void
+do_uninstall (HINSTANCE h)
+{
+  num_installs = 0, num_uninstalls = 0;
+
+  next_dialog = 0;             // we're done after this
+
+  if (!root_dir)
+    fatal ("no installation found");
+
+  int rv = DialogBox (h, MAKEINTRESOURCE (IDD_UNINSTALL), 0, dialog_proc);
+  if (rv == -1)
+    fatal (IDS_DIALOG_FAILED);
+}
+
+static void
+read_installed_db ()
+{
+  if (!root_dir)
+    return;
+
+  char line[1000], pkg[1000], inst[1000], src[1000];
+  int instsz, srcsz;
+
+  FILE *db = fopen (concat (root_dir, XEMACS_SETUP_DIR, "installed.db", 0), "rt");
+  if (!db)
+    return;
+
+  while (fgets (line, 1000, db))
+    {
+      src[0] = 0;
+      srcsz = 0;
+      sscanf (line, "%s %s %d %s %d", pkg, inst, &instsz, src, &srcsz);
+
+      log (0, "read %s", pkg);
+      Package* np = new_package(strdup(pkg));
+      pinfo(*np).install = inst;
+      pinfo(*np).install_size = instsz;
+      // pick up versoin
+      char *v, *d;
+      for (v=base (inst); *v; v++)
+       if (*v == '-' && isdigit(v[1]))
+         {
+           v++;
+           break;
+         }
+      if (!v)
+       v = inst;
+      for (d=v; *d; d++)
+       if (strncmp (d, ".tar", 4) == 0
+           || strncmp (d, "-pkg", 4) == 0)
+         {
+           *d = 0;
+           break;
+         }
+      if (v[0])
+       pinfo(*np).version = strdup (v);
+      else
+       pinfo(*np).version = "0";
+      // Crude but effective
+      if (pkg != 0)
+       if (strncmp ("xemacs-i686", pkg, 11) == 0
+           || (strncmp ("xemacs-i586", pkg, 11) == 0))
+         {
+           np->type = install_type;
+           xemacs_package = np;
+         }
+    }
+  fclose (db);
+}
+
+static DWORD WINAPI
+uninstall_all (void *)
+{
+  int i;
+  SetEvent (init_event);
+
+  int df = diskfull (root_dir);
+  SendMessage (unins_diskfull, PBM_SETPOS, (WPARAM) df, 0);
+
+  read_installed_db();
+
+  log (0, "There are %d packages\n", npackages);
+  for (i=0; i<npackages; i++)
+    {
+      log (0, "uninstalling %s\n", package[i].name);
+      uninstall_one (package[i].name, package[i].type, i);
+    }
+
+  PostMessage (unins_dialog, XM_DONE, 0, 0);
+
+  remove (concat (root_dir, XEMACS_SETUP_DIR, "installed.db.old", 0));
+  remove (concat (root_dir, XEMACS_SETUP_DIR, "installed.db", 0));
+
+  remove_desktop_setup();
+  remove_xemacs_root();
+  remove_uninstall_path();
+
+  if (num_installs == 0)
+    {
+      //      exit_msg = IDS_UNINSTALL_COMPLETE;
+      return FALSE;
+    }
+
+  return FALSE;
+}