This commit was manufactured by cvs2svn to create branch 'XEmacs-21_4'.
authortomo <tomo>
Mon, 13 Aug 2001 11:49:02 +0000 (11:49 +0000)
committertomo <tomo>
Mon, 13 Aug 2001 11:49:02 +0000 (11:49 +0000)
77 files changed:
netinstall/ChangeLog [new file with mode: 0644]
netinstall/Makefile.in.in [new file with mode: 0644]
netinstall/README [new file with mode: 0644]
netinstall/README.xemacs [new file with mode: 0644]
netinstall/autoload.c [new file with mode: 0644]
netinstall/check-na.bmp [new file with mode: 0644]
netinstall/check-no.bmp [new file with mode: 0644]
netinstall/check-yes.bmp [new file with mode: 0644]
netinstall/choose-rtarrow.bmp [new file with mode: 0644]
netinstall/choose-spin.bmp [new file with mode: 0644]
netinstall/choose.cc [new file with mode: 0644]
netinstall/concat.cc [new file with mode: 0644]
netinstall/concat.h [new file with mode: 0644]
netinstall/desktop.cc [new file with mode: 0644]
netinstall/dialog.cc [new file with mode: 0644]
netinstall/dialog.h [new file with mode: 0644]
netinstall/diskfull.cc [new file with mode: 0644]
netinstall/diskfull.h [new file with mode: 0644]
netinstall/download.cc [new file with mode: 0644]
netinstall/find.cc [new file with mode: 0644]
netinstall/find.h [new file with mode: 0644]
netinstall/fromcwd.cc [new file with mode: 0644]
netinstall/geturl.cc [new file with mode: 0644]
netinstall/geturl.h [new file with mode: 0644]
netinstall/gnu.bmp [new file with mode: 0644]
netinstall/hash.cc [new file with mode: 0644]
netinstall/hash.h [new file with mode: 0644]
netinstall/ini.cc [new file with mode: 0644]
netinstall/ini.h [new file with mode: 0644]
netinstall/inilex.l [new file with mode: 0644]
netinstall/iniparse.h [new file with mode: 0644]
netinstall/iniparse.y [new file with mode: 0644]
netinstall/install.cc [new file with mode: 0644]
netinstall/localdir.cc [new file with mode: 0644]
netinstall/log.cc [new file with mode: 0644]
netinstall/log.h [new file with mode: 0644]
netinstall/main.cc [new file with mode: 0644]
netinstall/mkdir.cc [new file with mode: 0644]
netinstall/mkdir.h [new file with mode: 0644]
netinstall/mklink2.c [new file with mode: 0644]
netinstall/msg.cc [new file with mode: 0644]
netinstall/msg.h [new file with mode: 0644]
netinstall/net.cc [new file with mode: 0644]
netinstall/netio.cc [new file with mode: 0644]
netinstall/netio.h [new file with mode: 0644]
netinstall/nio-file.cc [new file with mode: 0644]
netinstall/nio-file.h [new file with mode: 0644]
netinstall/nio-ftp.cc [new file with mode: 0644]
netinstall/nio-ftp.h [new file with mode: 0644]
netinstall/nio-http.cc [new file with mode: 0644]
netinstall/nio-http.h [new file with mode: 0644]
netinstall/nio-ie5.cc [new file with mode: 0644]
netinstall/nio-ie5.h [new file with mode: 0644]
netinstall/other.cc [new file with mode: 0644]
netinstall/port.h [new file with mode: 0644]
netinstall/postinstall.cc [new file with mode: 0644]
netinstall/regedit.cc [new file with mode: 0644]
netinstall/regedit.h [new file with mode: 0644]
netinstall/reginfo.h [new file with mode: 0644]
netinstall/res.rc [new file with mode: 0644]
netinstall/resource.h [new file with mode: 0644]
netinstall/root.cc [new file with mode: 0644]
netinstall/setup.mak [new file with mode: 0644]
netinstall/simpsock.cc [new file with mode: 0644]
netinstall/simpsock.h [new file with mode: 0644]
netinstall/site.cc [new file with mode: 0644]
netinstall/source.cc [new file with mode: 0644]
netinstall/splash.cc [new file with mode: 0644]
netinstall/state.cc [new file with mode: 0644]
netinstall/state.h [new file with mode: 0644]
netinstall/tar.cc [new file with mode: 0644]
netinstall/tar.h [new file with mode: 0644]
netinstall/version.h [new file with mode: 0644]
netinstall/version.pl [new file with mode: 0644]
netinstall/win32.h [new file with mode: 0644]
netinstall/xemacs.ico [new file with mode: 0644]
tests/redisplay-tests.el [new file with mode: 0644]

diff --git a/netinstall/ChangeLog b/netinstall/ChangeLog
new file mode 100644 (file)
index 0000000..8e2dad2
--- /dev/null
@@ -0,0 +1,128 @@
+2000-12-31  Martin Buchholz <martin@xemacs.org>
+
+       * XEmacs 21.2.39 is released.
+
+2000-12-28  Andy Piper  <andy@xemacs.org>
+
+       * desktop.cc (FROB): add more app paths.
+
+2000-12-24  Fabrice Popineau  <Fabrice.Popineau@supelec.fr>
+
+       * choose.cc (create_listview): CreateWindowEx() does not take this kind of
+       parameter.
+
+       * choose.cc (package_sort):
+       * hash.cc (rev_len):
+       * site.cc (site_sort): must be __cdecl to be called by qsort().
+
+       * download.cc:
+       * install.cc:
+       * nio-file.cc:
+       * tar.cc: because of the redefinition of stat to _stat, the
+       inclusion of win32 headers has to be delayed.
+       
+       * win32.h: added some declarations, such as CDECL if
+       not defined, #define for functions that are not standard in msvc
+       libc (strdup, stat ...)
+
+       * concat.h, concat.cc (concat): must be declared CDECL
+
+       * desktop.cc: <io.h> is needed.
+
+       * dialog.h (NEXT): cast needed, the first parameter of EndDialog() must
+       be a HWND.
+
+       * diskfull.cc: syntax when declaring GDFS.
+
+       * ini.cc: Various `extern "C"' declarations: yylineno, yyerror()
+       and fprintf(). Various CDECL declarations: yyerror(), fprintf().
+       
+       * inilex.l: <stdlib.h> required.
+       
+       * iniparse.y: use strdup(), require "win32.h" and <string.h>
+       
+       * install.cc (dialog): syntax when declaring. CreateDialog()
+       returns a HWND.
+       
+       * postinstall.cc: <io.h> and <stdio.h> are needed.
+       
+       * regedit.cc (find_cygwin_mount): WIN32_NATIVE does not know
+       anything about Cygwin stuff.
+       
+       * setup.mak: new makefile for WIN32_NATIVE.
+       
+       * splash.cc (load_dialog): GetDlgItem() returns a HWND.
+       
+       * tar.cc: msvc knows about __int64, but not `long long'.
+
+       * win32.h: <winreg.h> is missing for regedit.cc. Also, I ended up
+       in including <windows.h> because the files listed there are not
+       enough for <wininet.h>.
+       
+       * desktop.cc:
+       * fromcwd.cc:
+       * install.cc: 
+       * postinstall.cc: <unistd.h> does not exist for WIN32_NATIVE
+
+       * choose.cc (do_choose):
+       * ini.cc (do_ini):
+       * nio-ftp.cc (ftp_line): the construct (x ?: y) is not standard.
+
+2000-12-24  Andy Piper  <andy@xemacs.org>
+
+       * choose.cc (read_installed_db): grok package versions correctly.
+
+       * Makefile.in.in: add MINGW define.
+
+2000-12-18  Andy Piper  <andy@xemacs.org>
+
+       * res.rc: better look and feel.
+
+2000-12-18  Andy Piper  <andy@xemacs.org>
+
+       * desktop.cc (do_desktop_setup): more app path fiddling.
+
+2000-12-13  Andy Piper  <andy@xemacs.org>
+
+       * root.cc (dialog_cmd): create the root in the registry if we are successful.
+
+       * desktop.cc (find_xemacs_exe_path): new function. Split out from
+       find_xemacs_exe ().
+       (find_xemacs_exe_name): ditto.
+       (do_desktop_setup): setup app paths if we are installing xemacs
+       itself.
+       (do_desktop): use new functions.
+
+       * regedit.cc (create_xemacs_root): fix key name.
+       (find_xemacs_root): set isnative whatever the key value.
+       (set_app_path): new function. Set path for an app.
+
+2000-12-12  Andy Piper  <andy@xemacs.org>
+
+       * package-net.el (package-net-convert-index-to-ini): use sensible defaults.
+
+2000-12-12  Andy Piper  <andy@xemacs.org>
+
+       * reginfo.h: new macros.
+
+       * iniparse.y: define xemacs_package.
+
+       * ini.h: declare xemacs_package.
+
+       * fromcwd.cc (found_file): guess core type from name.
+
+       * concat.cc: kill warnings.
+       * net.cc: ditto.
+
+       * choose.cc (do_choose): pick up core package type chosen.
+
+       * Makefile.in.in: make sure we can pick up a mingw zlib.
+
+       * desktop.cc: fix desktop icon creation.
+
+2000-11-12  Andy Piper  <andy@xemacs.org>
+
+       * all: port from cygwin setup.
+
+%%% $Id: ChangeLog,v 1.1.2.4 2000/12/30 10:01:41 andyp Exp $
+$Revision: 1.1.2.4 $
diff --git a/netinstall/Makefile.in.in b/netinstall/Makefile.in.in
new file mode 100644 (file)
index 0000000..59dfb83
--- /dev/null
@@ -0,0 +1,252 @@
+## 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 Christopher Faylor <cgf@redhat.com>
+## Adapted for XEmacs by Andy Piper <andy@xemacs.org>
+##
+## Makefile for Cygwin installer
+
+## FIXME: integrate autoload.c so that wininet doesn't have to be linked.
+
+## For performance and consistency, no built-in rules
+.SUFFIXES:
+.SUFFIXES: .c .cc .h .o
+## ==================== Things "configure" will edit ====================
+
+@SET_MAKE@
+SHELL = /bin/sh
+RM = rm -f
+pwd = /bin/pwd
+
+CC=@CC@
+CPP=@CPP@
+CFLAGS=@CFLAGS@
+CPPFLAGS=@CPPFLAGS@
+LDFLAGS=@LDFLAGS@
+ALLOCA=@ALLOCA@
+LN_S=@LN_S@
+version=@version@
+
+## This will be the name of the generated binary and is set automatically
+## by configure.
+PROGNAME=@PROGNAME@
+INSTALLABLES=setup
+#ifdef USE_GNU_MAKE
+vpath %.c @srcdir@
+vpath %.cc @srcdir@
+vpath %.h @srcdir@
+#else
+VPATH=@srcdir@
+#endif
+
+## ==================== Where To Install Things ====================
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+libdir=@libdir@
+srcdir=@srcdir@
+datadir=@datadir@
+instvardir=@instvardir@
+top_srcdir=@top_srcdir@
+archlibdir=@archlibdir@
+configuration=@configuration@
+moduledir=@moduledir@
+sitemoduledir=@sitemoduledir@
+
+## ==================== Utility Programs for the Build =================
+
+INSTALL = @install_pp@ @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+SHELL = @SHELL@
+## ========================== Lists of Files ===========================
+
+#define NO_SHORTNAMES
+#define NOT_C_CODE
+#include "../src/config.h"
+
+program_transform_name = @program_transform_name@
+
+CC             = @CC@
+CC_FOR_TARGET  = $(CC)
+
+LOCALCFLAGS = $(CFLAGS) -DMINGW
+CXXFLAGS       = $(LOCALCFLAGS) -fno-exceptions -nostdinc++ -fno-rtti
+
+WINDRES                = windres
+MINGW_INCLUDES = -I. -I$(srcdir) 
+MINGW_CXXFLAGS = $(CXXFLAGS) -mno-cygwin $(MINGW_INCLUDES) -mwindows
+MINGW_CFLAGS   = $(LOCALCFLAGS) -mno-cygwin $(MINGW_INCLUDES) -mwindows
+MINGW_ZLIB_DIR = /usr/local/lib
+
+PROGS  = setup.exe
+
+CONFIG_H = ../src/config.h
+
+OBJS = \
+       choose.o \
+       concat.o \
+       desktop.o \
+       dialog.o \
+       diskfull.o \
+       download.o \
+       find.o \
+       fromcwd.o \
+       geturl.o \
+       hash.o \
+       ini.o \
+       inilex.o \
+       iniparse.o \
+       install.o \
+       localdir.o \
+       log.o \
+       main.o \
+       mkdir.o \
+       mklink2.o \
+       regedit.o \
+       msg.o \
+       net.o \
+       netio.o \
+       nio-ie5.o \
+       nio-file.o \
+       nio-ftp.o \
+       nio-http.o \
+       other.o \
+       postinstall.o \
+       res.o \
+       root.o \
+       simpsock.o \
+       site.o \
+       source.o \
+       splash.o \
+       state.o \
+       tar.o \
+       version.o
+
+.SUFFIXES:
+.NOEXPORT:
+
+.PHONY: all install
+
+all: Makefile $(PROGS)
+
+setup.exe: $(OBJS)
+       $(CXX) $(MINGW_CXXFLAGS) -o $@ $(OBJS) \
+               -lole32 -lwsock32 -lnetapi32 -ladvapi32 \
+               -luuid -lkernel32 -luser32 -lwininet \
+               -L$(MINGW_ZLIB_DIR) -lz -lmingw32
+       @chmod a-x $@
+
+install:
+       @echo; echo "Installing net setup."
+       for file in ${INSTALLABLES} ; do \
+         (cd .. && $(INSTALL_PROGRAM) netinstall/$${file} ${bindir}/$${file}) ; \
+       done
+
+version.c : $(srcdir)/ChangeLog Makefile
+       V=`grep '^\$$Revision.*' $(srcdir)/ChangeLog \
+       | sed -e 's/\$$Revision:* *//' \
+         -e 's/ *$$.*//'` ;\
+       echo "char *version = \"$$V\";" > version.tmp ;\
+       echo "static char *id = \"\\n%%% setup-version $$V\\n\";" >> version.tmp
+       mv version.tmp version.c
+
+%.o: %.rc
+       $(WINDRES) --include-dir $(srcdir) -o $@ $<
+
+%.o: %.c
+       $(CC) $(MINGW_CFLAGS) -c -o $@ ${srcdir}/$<
+
+%.o: %.cc
+       $(CC) $(MINGW_CXXFLAGS) -c -o $@ ${srcdir}/$<
+
+iniparse.c iniparse.h : iniparse.y
+       bison -d -o iniparse.c $(srcdir)/iniparse.y
+
+inilex.c : inilex.l iniparse.h
+       flex -8 $(srcdir)/inilex.l
+       mv lex.yy.c inilex.c
+
+.PHONY: mostlyclean clean distclean realclean extraclean
+
+mostlyclean:
+       $(RM) *.o *.i core $(PROGS)
+
+clean: mostlyclean
+
+distclean: clean
+       $(RM) GNUmakefile Makefile Makefile.in TAGS
+
+realclean: distclean
+
+extraclean: distclean
+       $(RM) *~ \#*
+
+choose.o: choose.cc win32.h dialog.h resource.h state.h ini.h concat.h \
+ msg.h log.h find.h reginfo.h
+concat.o: concat.cc
+desktop.o: desktop.cc win32.h resource.h ini.h msg.h state.h concat.h \
+ mkdir.h dialog.h version.h port.h
+dialog.o: dialog.cc win32.h dialog.h msg.h log.h
+diskfull.o: diskfull.cc win32.h diskfull.h
+download.o: download.cc win32.h resource.h msg.h ini.h dialog.h \
+ concat.h geturl.h state.h mkdir.h log.h
+find.o: find.cc win32.h port.h
+fromcwd.o: fromcwd.cc win32.h ini.h resource.h concat.h state.h \
+ dialog.h msg.h find.h version.h port.h
+geturl.o: geturl.cc win32.h dialog.h \
+ geturl.h resource.h netio.h msg.h log.h
+hash.o: hash.cc hash.h
+ini.o: ini.cc win32.h ini.h resource.h concat.h state.h geturl.h \
+ dialog.h msg.h mkdir.h log.h reginfo.h version.h
+inilex.o: inilex.c win32.h \
+ ini.h \
+ iniparse.h
+iniparse.o: iniparse.c ini.h \
+ iniparse.h \
+ port.h
+install.o: install.cc win32.h \
+ resource.h ini.h dialog.h concat.h geturl.h mkdir.h state.h tar.h \
+ diskfull.h msg.h regedit.h reginfo.h log.h hash.h port.h
+localdir.o: localdir.cc win32.h dialog.h resource.h state.h msg.h \
+ concat.h log.h
+log.o: log.cc win32.h resource.h msg.h log.h dialog.h state.h concat.h \
+ mkdir.h
+main.o: main.cc win32.h resource.h dialog.h state.h msg.h netio.h \
+ find.h log.h port.h
+mkdir.o: mkdir.cc win32.h mkdir.h
+mklink2.o: mklink2.c win32.h /usr/include/w32api/shlobj.h
+msg.o: msg.cc win32.h dialog.h log.h
+net.o: net.cc win32.h dialog.h resource.h state.h msg.h log.h
+netio.o: netio.cc win32.h resource.h state.h msg.h netio.h nio-file.h \
+ nio-ie5.h nio-http.h nio-ftp.h dialog.h log.h port.h
+nio-file.o: nio-file.cc win32.h netio.h nio-file.h resource.h msg.h
+nio-ftp.o: nio-ftp.cc win32.h resource.h state.h simpsock.h log.h \
+ netio.h nio-ftp.h
+nio-http.o: nio-http.cc win32.h resource.h state.h simpsock.h msg.h \
+ netio.h nio-http.h
+nio-ie5.o: nio-ie5.cc win32.h resource.h state.h dialog.h msg.h \
+ netio.h nio-ie5.h
+other.o: other.cc win32.h dialog.h resource.h state.h msg.h log.h
+postinstall.o: postinstall.cc win32.h state.h dialog.h find.h concat.h \
+ port.h
+regedit.o: regedit.cc win32.h reginfo.h regedit.h msg.h resource.h \
+ dialog.h
+root.o: root.cc win32.h dialog.h resource.h state.h msg.h regedit.h \
+ reginfo.h concat.h log.h
+simpsock.o: simpsock.cc win32.h simpsock.h msg.h
+site.o: site.cc win32.h dialog.h resource.h state.h geturl.h msg.h \
+ concat.h regedit.h reginfo.h log.h port.h
+source.o: source.cc win32.h dialog.h resource.h state.h msg.h log.h
+splash.o: splash.cc win32.h dialog.h resource.h msg.h version.h
+state.o: state.cc state.h
+tar.o: tar.cc win32.h tar.h mkdir.h log.h port.h
+version.o: version.c
diff --git a/netinstall/README b/netinstall/README
new file mode 100644 (file)
index 0000000..21d1877
--- /dev/null
@@ -0,0 +1,25 @@
+This directory contains the source for the setup program for the cygwin
+net releases.
+
+
+
+To-Do list:
+
+ini.cc: add field in setup.ini to specify whether package is installed
+by default, or not.
+
+install.cc: scan newly installed files for README files, show list to
+user, let them read them if they want.
+
+download.cc: add a "total progress" indicator, like the install one.
+
+add a "category" field to setup.ini, let user choose which categories
+of packages to install, perhaps with a "custom..." button to lead to
+the current chooser.
+
+remember which packages were selected to be skipped, and which prev/curr/exp
+option was last selected, and recall them each time the chooser runs.
+
+Add friendly error reporting to simpsock.cc
+
+Add option to download sources also.
diff --git a/netinstall/README.xemacs b/netinstall/README.xemacs
new file mode 100644 (file)
index 0000000..f962e65
--- /dev/null
@@ -0,0 +1,23 @@
+This directory contains the source for the setup program for the
+XEmacs net releases. 
+
+This code has been adapted from the cygwin net release installer. In
+particular note that the cygwin net release installer is actively
+maintained and therefore we will want to incorporate improvements from
+that. I have therefore tried to use the cygwin way wherever
+possible. I have however cleaned up the code somewhat so that there
+are not billions of warnings.
+
+This program should get built as part of the standard XEmacs
+make. Note however that if you use trhe cygwin build you will need a
+NON CYGWIN VERSION OF ZLIB.
+
+New files:
+       regedit.cc:     
+       regedit.h
+       reginfo.h
+       Makefile.in.in: 
+
+Deleted files:
+       mount.cc:       moved to regedit.cc
+       mount.h:        moved to regedit.h
diff --git a/netinstall/autoload.c b/netinstall/autoload.c
new file mode 100644 (file)
index 0000000..6fae77c
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * 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 "win32.h"
+
+typedef struct {
+  char *name;
+  HINSTANCE handle;
+} DllInfo;
+
+#define DLL(n) static DllInfo n ## _info __asm__ (#n "_info") = { #n, 0}
+
+#define Auto(dll, func, size) \
+       __asm__ ("\t.data"); \
+       __asm__ ("\t.global\t_" #func "@" #size); \
+       __asm__ ("_" #func "@" #size ":"); \
+       __asm__ ("\tcall\tautoload_common"); \
+       __asm__ ("\t.long\t" #dll "_info"); \
+       __asm__ ("\t.ascii\t\"" #func "\\0\"")
+
+DLL (wininet);
+
+Auto (wininet, InternetAttemptConnect, 4);
+Auto (wininet, InternetCloseHandle, 4);
+Auto (wininet, InternetGetLastResponseInfoA, 12);
+Auto (wininet, InternetOpenA, 20);
+Auto (wininet, InternetOpenUrlA, 24);
+Auto (wininet, InternetReadFile, 16);
+Auto (wininet, InternetSetOptionA, 16);
+Auto (wininet, InternetQueryOptionA, 16);
+Auto (wininet, HttpQueryInfoA, 20);
+Auto (wininet, HttpSendRequestA, 20);
+
+typedef struct {
+  DllInfo *dll;
+  char name[100];
+} AutoEntry;
+
+static void autoload_common () __asm__ ("autoload_common");
+
+static void
+autoload_common (int x)
+{
+  int fp, rel;
+  unsigned char *proc;
+  HINSTANCE h;
+  AutoEntry *a;
+  
+  a = *(AutoEntry **)(&x - 1);
+  if (a->dll->handle == 0)
+    {
+      h = LoadLibrary (a->dll->name);
+      a->dll->handle = h;
+    }
+  fp = (int) GetProcAddress (a->dll->handle, a->name);
+  proc = ((unsigned char *)a) - 5;
+  rel = fp - (int)(a); /* now it's a relative call */
+  *proc++ = 0xe9; /* jump near 32-bit relative */
+  *proc++ = rel;
+  *proc++ = rel>>8;
+  *proc++ = rel>>16;
+  *proc++ = rel>>24;
+
+  *(int *)(&x-1) = (int)proc-5;
+}
diff --git a/netinstall/check-na.bmp b/netinstall/check-na.bmp
new file mode 100644 (file)
index 0000000..c139e54
Binary files /dev/null and b/netinstall/check-na.bmp differ
diff --git a/netinstall/check-no.bmp b/netinstall/check-no.bmp
new file mode 100644 (file)
index 0000000..3639605
Binary files /dev/null and b/netinstall/check-no.bmp differ
diff --git a/netinstall/check-yes.bmp b/netinstall/check-yes.bmp
new file mode 100644 (file)
index 0000000..f328dc2
Binary files /dev/null and b/netinstall/check-yes.bmp differ
diff --git a/netinstall/choose-rtarrow.bmp b/netinstall/choose-rtarrow.bmp
new file mode 100644 (file)
index 0000000..5f719e1
Binary files /dev/null and b/netinstall/choose-rtarrow.bmp differ
diff --git a/netinstall/choose-spin.bmp b/netinstall/choose-spin.bmp
new file mode 100644 (file)
index 0000000..8779f6d
Binary files /dev/null and b/netinstall/choose-spin.bmp differ
diff --git a/netinstall/choose.cc b/netinstall/choose.cc
new file mode 100644 (file)
index 0000000..40d4bc8
--- /dev/null
@@ -0,0 +1,831 @@
+/*
+ * 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 let the user choose which packages
+   to install, and which versions of the package when more than one
+   version is provided.  The "trust" level serves as an indication as
+   to which version should be the default choice.  At the moment, all
+   we do is compare with previously installed packages to skip any
+   that are already installed (by setting the action to ACTION_SAME).
+   While the "trust" stuff is supported, it's not really implemented
+   yet.  We always prefer the "current" option.  In the future, this
+   file might have a user dialog added to let the user choose to not
+   install packages, or to install packages that aren't installed by
+   default. */
+
+#include "win32.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "dialog.h"
+#include "resource.h"
+#include "state.h"
+#include "ini.h"
+#include "concat.h"
+#include "msg.h"
+#include "log.h"
+#include "find.h"
+#include "reginfo.h"
+
+#define HMARGIN                10
+#define ROW_MARGIN     5
+#define ICON_MARGIN    4
+
+#define CHECK_SIZE     11
+
+#define TRUST_KEEP     101
+#define TRUST_UNINSTALL        102
+#define TRUST_NONE     103
+
+static int initialized = 0;
+
+static int full_list = 0;
+
+static int scroll_ulc_x, scroll_ulc_y;
+
+static HWND lv, nextbutton;
+static TEXTMETRIC tm;
+static int header_height;
+static HANDLE sysfont;
+static int row_height;
+static HANDLE bm_spin, bm_rtarrow, bm_checkyes, bm_checkno, bm_checkna;
+static HDC bitmap_dc;
+
+static struct {
+  char *text;
+  int slen;
+  int width;
+  int x;
+} headers[] = {
+  { "Current", 7, 0, 0 },
+#define CURRENT_COL 0
+  { "New", 3, 0, 0 },
+#define NEW_COL 1
+  { "Src?", 4, 0, 0 },
+#define SRC_COL 2
+  { "Package", 7, 0, 0 },
+#define PACKAGE_COL 3
+  { 0, 0, 0, 0 }
+};
+#define NUM_COLUMNS (sizeof(headers)/(sizeof(headers[0]))-1)
+
+int *package_indexes, nindexes;
+
+struct ExtraPackageInfo {
+  char *installed_file;        /* filename of previous "install" file */
+  char *installed_ver; /* version part */
+  int   installed_size; /* ditto, size. */
+
+  int in_partial_list;
+  int pick;
+  int npick;
+  int which_is_installed; /* == TRUST* or -1 */
+
+  struct {
+    int src_avail;
+    int trust;         /* may be keep or uninstall */
+    char *caption;     /* ==0 at EOL */
+  } chooser[NTRUST+3]; /* one extra for NULL above */
+};
+
+static ExtraPackageInfo *extra;
+
+static void
+paint (HWND hwnd)
+{
+  HDC hdc;
+  PAINTSTRUCT ps;
+  int x, y, i, ii;
+
+  hdc = BeginPaint (hwnd, &ps);
+
+  SelectObject (hdc, sysfont);
+
+  RECT cr;
+  GetClientRect (hwnd, &cr);
+
+  POINT p;
+
+  x = cr.left - scroll_ulc_x;
+  y = cr.top - scroll_ulc_y + header_height;
+
+
+  for (i=0; headers[i].text; i++)
+    {
+      TextOut (hdc, x+headers[i].x, 3, headers[i].text, headers[i].slen);
+      MoveToEx (hdc, x+headers[i].x, header_height-3, &p);
+      LineTo (hdc, x+headers[i].x+headers[i].width, header_height-3);
+    }
+
+  IntersectClipRect (hdc, cr.left, cr.top+header_height, cr.right, cr.bottom);
+
+  for (ii=0; ii<nindexes; ii++)
+    {
+      i = package_indexes[ii];
+      int r = y + ii * row_height;
+      int by = r + tm.tmHeight - 11;
+      if (extra[i].installed_ver && extra[i].installed_ver[0])
+       {
+         TextOut (hdc, x+headers[CURRENT_COL].x, r,
+                  extra[i].installed_ver, strlen (extra[i].installed_ver));
+         SelectObject (bitmap_dc, bm_rtarrow);
+         BitBlt (hdc, x+headers[CURRENT_COL].x+headers[0].width+ICON_MARGIN/2+HMARGIN/2, by,
+                 11, 11, bitmap_dc, 0, 0, SRCCOPY);
+       }
+
+      char *s = extra[i].chooser[extra[i].pick].caption;
+      if (s)
+       {
+         TextOut (hdc, x+headers[NEW_COL].x + 11 + ICON_MARGIN, r,
+                  s, strlen (s));
+         if (extra[i].npick > 1)
+           {
+             SelectObject (bitmap_dc, bm_spin);
+             BitBlt (hdc, x+headers[NEW_COL].x, by, 11, 11,
+                     bitmap_dc, 0, 0, SRCCOPY);
+           }
+       }
+
+      HANDLE check_bm = bm_checkna;
+      if (extra[i].chooser[extra[i].pick].src_avail)
+       {
+         if (package[i].srcaction == SRCACTION_NO)
+           check_bm = bm_checkno;
+         else if (package[i].srcaction == SRCACTION_YES)
+           check_bm = bm_checkyes;
+       }
+      SelectObject (bitmap_dc, check_bm);
+      BitBlt (hdc, x+headers[SRC_COL].x, by, 11, 11,
+             bitmap_dc, 0, 0, SRCCOPY);
+
+      if (package[i].name)
+       TextOut (hdc, x+headers[PACKAGE_COL].x, r, package[i].name, strlen(package[i].name));
+    }
+
+  if (nindexes == 0)
+    {
+      static char *m = "Nothing to Install/Update";
+      TextOut (hdc, HMARGIN, header_height, m, strlen (m));
+    }
+  
+  EndPaint (hwnd, &ps);
+}
+
+static void
+scroll_common (HWND hwnd, int which, int *var, int code)
+{
+  SCROLLINFO si;
+  si.cbSize = sizeof (si);
+  si.fMask = SIF_ALL;
+  GetScrollInfo (hwnd, which, &si);
+
+  switch (code)
+    {
+    case SB_THUMBTRACK:
+      si.nPos = si.nTrackPos;
+      break;
+    case SB_THUMBPOSITION:
+      break;
+    case SB_BOTTOM:
+      si.nPos = si.nMax;
+      break;
+    case SB_TOP:
+      si.nPos = 0;
+      break;
+    case SB_LINEDOWN:
+      si.nPos += row_height;
+      break;
+    case SB_LINEUP:
+      si.nPos -= row_height;
+      break;
+    case SB_PAGEDOWN:
+      si.nPos += si.nPage * 9/10;
+      break;
+    case SB_PAGEUP:
+      si.nPos -= si.nPage * 9/10;
+      break;
+    }
+
+  if ((int)si.nPos < 0)
+    si.nPos = 0;
+  if ((int)(si.nPos + si.nPage) > si.nMax)
+    si.nPos = si.nMax - si.nPage;
+
+  si.fMask = SIF_POS;
+  SetScrollInfo (hwnd, which, &si, TRUE);
+
+  int ox = scroll_ulc_x;
+  int oy = scroll_ulc_y;
+  *var = si.nPos;
+
+  RECT cr, sr;
+  GetClientRect (hwnd, &cr);
+  sr = cr;
+  sr.top += header_height;
+  ScrollWindow (hwnd, ox - scroll_ulc_x, oy - scroll_ulc_y, &sr, &sr);
+  sr.bottom = sr.top;
+  sr.top = cr.top;
+  ScrollWindow (hwnd, ox - scroll_ulc_x, 0, &sr, &sr);
+}
+
+static LRESULT CALLBACK
+list_vscroll (HWND hwnd, HWND hctl, UINT code, int pos)
+{
+  scroll_common (hwnd, SB_VERT, &scroll_ulc_y, code);
+  return FALSE;
+}
+
+static LRESULT CALLBACK
+list_hscroll (HWND hwnd, HWND hctl, UINT code, int pos)
+{
+  scroll_common (hwnd, SB_HORZ, &scroll_ulc_x, code);
+  return FALSE;
+}
+
+static LRESULT CALLBACK
+list_click (HWND hwnd, BOOL dblclk, int x, int y, UINT hitCode)
+{
+  int r;
+
+  if (nindexes == 0)
+    return 0;
+
+  if (y < header_height)
+    return 0;
+  x += scroll_ulc_x;
+  y += scroll_ulc_y - header_height;
+
+  r = (y + ROW_MARGIN/2) / row_height;
+
+  if (r < 0 || r >= npackages)
+    return 0;
+
+  int p = package_indexes[r];
+
+  if (x >= headers[NEW_COL].x - HMARGIN/2 && x <= headers[NEW_COL+1].x - HMARGIN/2)
+    {
+      extra[p].pick ++;
+      if (extra[p].chooser[extra[p].pick].caption == 0)
+       extra[p].pick = 0;
+    }
+
+  if (x >= headers[SRC_COL].x - HMARGIN/2 && x <= headers[SRC_COL+1].x - HMARGIN/2)
+    {
+      if (extra[p].chooser[extra[p].pick].src_avail)
+       package[p].srcaction ^= (SRCACTION_NO^SRCACTION_YES);
+    }
+
+  RECT rect;
+  rect.left = headers[NEW_COL].x - scroll_ulc_x;
+  rect.right = headers[SRC_COL+1].x - scroll_ulc_x;
+  rect.top = header_height + r * row_height - scroll_ulc_y;
+  rect.bottom = rect.top + row_height;
+  InvalidateRect (hwnd, &rect, TRUE);
+  return FALSE;
+}
+
+static LRESULT CALLBACK
+listview_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  switch (message) {
+  case WM_HSCROLL:
+    return HANDLE_WM_HSCROLL (hwnd, wParam, lParam, list_hscroll);
+  case WM_VSCROLL:
+    return HANDLE_WM_VSCROLL (hwnd, wParam, lParam, list_vscroll);
+  case WM_LBUTTONDOWN:
+    return HANDLE_WM_LBUTTONDOWN (hwnd, wParam, lParam, list_click);
+  case WM_PAINT:
+    paint (hwnd);
+    return 0;
+  default:
+    return DefWindowProc (hwnd, message, wParam, lParam);
+  }
+}
+
+static void
+register_windows (HINSTANCE hinst)
+{
+  WNDCLASSEX wcex;
+  static int done = 0;
+
+  if (done)
+    return;
+  done = 1;
+
+  memset (&wcex, 0, sizeof (wcex));
+  wcex.cbSize = sizeof (WNDCLASSEX);
+  wcex.style = CS_HREDRAW | CS_VREDRAW;
+  wcex.lpfnWndProc = listview_proc;
+  wcex.hInstance = hinst;
+  wcex.hIcon = LoadIcon (0, IDI_APPLICATION);
+  wcex.hCursor = LoadCursor (0, IDC_ARROW);
+  wcex.hbrBackground = (HBRUSH) (COLOR_WINDOW+1);
+  wcex.lpszClassName = "listview";
+
+  RegisterClassEx (&wcex);
+}
+
+static void
+note_width (HDC dc, char *string, int addend, int column)
+{
+  if (!string)
+    return;
+  SIZE s;
+  GetTextExtentPoint32 (dc, string, strlen (string), &s);
+  if (headers[column].width < s.cx + addend)
+    headers[column].width = s.cx + addend;
+}
+
+static int
+best_trust (int p, int trust)
+{
+  int t;
+  for (t=trust; t>=0; t--)
+    if (package[p].info[t].install)
+      return t;
+  for (t=trust+1; t<=NTRUST; t++)
+    if (package[p].info[t].install)
+      return t;
+  if (extra[p].installed_file)
+    return TRUST_KEEP;
+  return TRUST_NONE;
+}
+
+static void
+default_trust (HWND h, int trust)
+{
+  int i, t, c;
+
+  for (i=0; i<npackages; i++)
+    {
+      t = best_trust (i, trust);
+      extra[i].pick = 1;
+      for (c=0; c<extra[i].npick; c++)
+       if (t == extra[i].chooser[c].trust)
+         extra[i].pick = c;
+      if (install_type == IDC_INSTALL_NATIVE 
+         && package[i].type == TY_CYGWIN
+         ||
+         install_type == IDC_INSTALL_CYGWIN 
+         && package[i].type == TY_NATIVE)
+       extra[i].pick = extra[i].npick -1;
+    }
+  RECT r;
+  GetClientRect (h, &r);
+  InvalidateRect (h, &r, TRUE);
+  if (nextbutton)
+    SetFocus (nextbutton);
+}
+
+static void
+set_full_list (HWND h, int isfull)
+{
+  int i, j;
+  full_list = isfull;
+  if (package_indexes == 0)
+    package_indexes = (int *) malloc (npackages * sizeof (int));
+  for (i=j=0; i<npackages; i++)
+    {
+      if (isfull || extra[i].in_partial_list)
+       package_indexes[j++] = i;
+    }
+  nindexes = j;
+
+  RECT r;
+  GetClientRect (h, &r);
+  SCROLLINFO si;
+  memset (&si, 0, sizeof (si));
+  si.cbSize = sizeof (si);
+  si.fMask = SIF_ALL;
+  si.nMin = 0;
+  si.nMax = headers[2].x + headers[2].width + HMARGIN;
+  si.nPage = r.right;
+  SetScrollInfo (h, SB_HORZ, &si, TRUE);
+
+  si.nMax = nindexes * row_height;
+  si.nPage = r.bottom - header_height;
+  SetScrollInfo (h, SB_VERT, &si, TRUE);
+
+  scroll_ulc_x = scroll_ulc_y = 0;
+
+  InvalidateRect (h, &r, TRUE);
+
+  if (nextbutton)
+    SetFocus (nextbutton);
+}
+
+static void
+build_labels ()
+{
+  int i;
+  for (i=0; i<npackages; i++)
+    {
+      int c = 0, t;
+
+#define C extra[i].chooser[c]
+      if (extra[i].installed_ver)
+       {
+         C.caption = "Uninstall";
+         C.trust = TRUST_UNINSTALL;
+         c++;
+         C.caption = "Keep";
+         C.trust = TRUST_KEEP;
+         c++;
+       }
+
+      for (t=TRUST_PREV; t<NTRUST; t++)
+       if (package[i].info[t].install)
+         if (t != extra[i].which_is_installed)
+           {
+             C.caption = package[i].info[t].version;
+             if (C.caption == 0 || C.caption[0] == 0)
+               C.caption = "0.0";
+             C.trust = t;
+             if (package[i].info[t].source)
+               C.src_avail = 1;
+             c++;
+             /* we intentionally skip TRUST_PREV */
+             if (t != TRUST_PREV || !extra[i].installed_ver)
+               extra[i].in_partial_list = 1;
+
+           }
+
+      if (c == 0)
+       {
+         C.caption = "N/A";
+         C.trust = TRUST_NONE;
+         c++;
+       }
+
+      if (! extra[i].installed_file)
+       {
+         C.caption = "Skip";
+         C.trust = TRUST_NONE;
+         c++;
+       }
+
+      C.caption = 0;
+      extra[i].npick = c;
+#undef C
+    }
+}
+
+static void
+create_listview (HWND dlg, RECT *r)
+{
+  int i, t;
+  lv = CreateWindowEx (WS_EX_CLIENTEDGE,
+                      "listview",
+                      "listviewwindow",
+                      WS_CHILD | WS_HSCROLL | WS_VSCROLL | WS_VISIBLE,
+                      r->left, r->top,
+                      r->right-r->left+1, r->bottom-r->top+1,
+                      dlg,
+                      NULL, // ??? MAKEINTRESOURCE(IDC_CHOOSE_LIST),
+                      hinstance,
+                      0);
+  ShowWindow (lv, SW_SHOW);
+
+  for (i=0; headers[i].text; i++)
+    headers[i].width = 0;
+
+  HDC dc = GetDC (lv);
+  sysfont = GetStockObject (DEFAULT_GUI_FONT);
+  SelectObject (dc, sysfont);
+  GetTextMetrics (dc, &tm);
+  header_height = tm.tmHeight + 5 + 3;
+
+  bitmap_dc = CreateCompatibleDC (dc);
+
+  row_height = (tm.tmHeight + tm.tmExternalLeading + ROW_MARGIN);
+  int irh = tm.tmExternalLeading + tm.tmDescent + 11 + ROW_MARGIN;
+  if (row_height < irh)
+    row_height = irh;
+
+  for (i=0; headers[i].text; i++)
+    note_width (dc, headers[i].text, 0, i);
+  for (i=0; i<npackages; i++)
+    {
+      note_width (dc, extra[i].installed_ver, 0, CURRENT_COL);
+      note_width (dc, extra[i].installed_ver, 11+ICON_MARGIN, NEW_COL);
+      for (t=0; t<NTRUST; t++)
+       note_width (dc, package[i].info[t].version, 11+ICON_MARGIN, NEW_COL);
+      note_width (dc, package[i].name, 0, PACKAGE_COL);
+      note_width (dc, package[i].sdesc, 0, PACKAGE_COL);
+    }
+  note_width (dc, "keep", 11+ICON_MARGIN, NEW_COL);
+  note_width (dc, "uninstall", 11+ICON_MARGIN, NEW_COL);
+
+  headers[CURRENT_COL].x = HMARGIN/2;
+  headers[NEW_COL].x = (headers[CURRENT_COL].x + headers[CURRENT_COL].width
+                       + HMARGIN + 11 + ICON_MARGIN);
+  headers[SRC_COL].x = headers[NEW_COL].x + headers[NEW_COL].width + HMARGIN;
+  headers[PACKAGE_COL].x = headers[SRC_COL].x + headers[SRC_COL].width + HMARGIN;
+
+  set_full_list (lv, full_list);
+  default_trust (lv, TRUST_CURR);
+
+  ReleaseDC (lv, dc);
+}
+
+static BOOL
+dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
+{
+  switch (id)
+    {
+
+    case IDC_CHOOSE_PREV:
+      default_trust (lv, TRUST_PREV);
+      break;
+    case IDC_CHOOSE_CURR:
+      default_trust (lv, TRUST_CURR);
+      break;
+    case IDC_CHOOSE_EXP:
+      default_trust (lv, TRUST_TEST);
+      break;
+    case IDC_CHOOSE_FULLPART:
+      set_full_list (lv, !full_list);
+      break;
+
+    case IDOK:
+      if (source == IDC_SOURCE_CWD)
+       NEXT (IDD_S_INSTALL);
+      else
+       NEXT (IDD_S_DOWNLOAD);
+      break;
+
+    case IDC_BACK:
+      initialized = 0;
+      if (source == IDC_SOURCE_CWD)
+       NEXT (IDD_ROOT);
+      else
+       NEXT (IDD_SITE);
+      break;
+
+    case IDCANCEL:
+      NEXT (0);
+      break;
+    }
+  return FALSE;
+}
+
+static void
+GetParentRect (HWND parent, HWND child, RECT *r)
+{
+  POINT p;
+  GetWindowRect (child, r);
+  p.x = r->left;
+  p.y = r->top;
+  ScreenToClient (parent, &p);
+  r->left = p.x;
+  r->top = p.y;
+  p.x = r->right;
+  p.y = r->bottom;
+  ScreenToClient (parent, &p);
+  r->right = p.x;
+  r->bottom = p.y;
+}
+
+static BOOL CALLBACK
+dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  HWND frame;
+  RECT r;
+  switch (message)
+    {
+    case WM_INITDIALOG:
+      nextbutton = GetDlgItem (h, IDOK);
+      frame = GetDlgItem (h, IDC_LISTVIEW_POS);
+      GetParentRect (h, frame, &r);
+      r.top += 2;
+      r.bottom -= 2;
+      create_listview (h, &r);
+#if 0
+      load_dialog (h);
+#endif
+      return FALSE;
+    case WM_COMMAND:
+      return HANDLE_WM_COMMAND (h, wParam, lParam, dialog_cmd);
+    }
+  return FALSE;
+}
+
+static char *
+base (char *s)
+{
+  if (!s)
+    return 0;
+  char *rv = s;
+  while (*s)
+    {
+      if ((*s == '/' || *s == ':' || *s == '\\') && s[1])
+       rv = s+1;
+      s++;
+    }
+  return rv;
+}
+
+static void
+scan2 (char *path, unsigned int size)
+{
+  int i, t;
+  for (i=0; i<npackages; i++)
+    for (t=0; t<NTRUST; t++)
+      if (package[i].info[t].install
+         && strcmp (base (package[i].info[t].install), base (path)) == 0
+         && package[i].info[t].install_size == (int)size)
+       {
+         extra[i].installed_file = package[i].info[t].install;
+         extra[i].installed_size = size;
+         extra[i].which_is_installed = t;
+         extra[i].installed_ver = package[i].info[t].version;
+         if (!extra[i].installed_ver)
+           extra[i].installed_ver = "0";
+       }
+}
+
+static void
+scan_downloaded_files ()
+{
+  find (".", scan2);
+}
+
+static void
+read_installed_db ()
+{
+  int i;
+  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);
+
+      for (i=0; i<npackages; i++)
+       if (strcmp (package[i].name, pkg) == 0)
+         {
+           int t;
+           extra[i].installed_file = inst;
+           extra[i].installed_size = instsz;
+
+           for (t=0; t<NTRUST; t++)
+             if (package[i].info[t].install
+                 && strcmp (base (package[i].info[t].install), base (inst)) == 0)
+               {
+                 extra[i].which_is_installed = t;
+                 extra[i].installed_ver = package[i].info[t].version;
+                 break;
+               }
+
+           if (extra[i].installed_ver == 0) /* still */
+             {
+               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])
+                 extra[i].installed_ver = strdup (v);
+               else
+                 extra[i].installed_ver = "0";
+             }
+           break;
+         }
+    }
+  fclose (db);
+}
+
+int CDECL
+package_sort (const void *va, const void *vb)
+{
+  Package *a = (Package *)va;
+  Package *b = (Package *)vb;
+  return strcmp (a->name, b->name);
+}
+
+void
+do_choose (HINSTANCE h)
+{
+  int rv, i;
+
+  qsort (package, npackages, sizeof (package[0]), package_sort);
+
+  nextbutton = 0;
+  bm_spin = LoadImage (h, MAKEINTRESOURCE (IDB_SPIN), IMAGE_BITMAP, 0, 0, 0);
+  bm_rtarrow = LoadImage (h, MAKEINTRESOURCE (IDB_RTARROW), IMAGE_BITMAP, 0, 0, 0);
+
+  bm_checkyes = LoadImage (h, MAKEINTRESOURCE (IDB_CHECK_YES), IMAGE_BITMAP, 0, 0, 0);
+  bm_checkno = LoadImage (h, MAKEINTRESOURCE (IDB_CHECK_NO), IMAGE_BITMAP, 0, 0, 0);
+  bm_checkna = LoadImage (h, MAKEINTRESOURCE (IDB_CHECK_NA), IMAGE_BITMAP, 0, 0, 0);
+
+  extra = (ExtraPackageInfo *) malloc (npackages * sizeof (ExtraPackageInfo));
+  memset (extra, 0, npackages * sizeof (ExtraPackageInfo));
+  for (i=0; i<npackages; i++)
+    extra[i].which_is_installed = -1;
+
+  register_windows (h);
+
+  if (source == IDC_SOURCE_DOWNLOAD)
+    scan_downloaded_files ();
+  else
+    read_installed_db ();
+  build_labels ();
+
+  rv = DialogBox (h, MAKEINTRESOURCE (IDD_CHOOSE), 0, dialog_proc);
+  if (rv == -1)
+    fatal (IDS_DIALOG_FAILED);
+
+  for (i=0; i<npackages; i++)
+    {
+      switch (extra[i].chooser[extra[i].pick].trust)
+       {
+       case TRUST_PREV:
+       case TRUST_CURR:
+       case TRUST_TEST:
+         if (extra[i].installed_file)
+           package[i].action = ACTION_UPGRADE;
+         else
+           package[i].action = ACTION_NEW;
+         package[i].trust = extra[i].chooser[extra[i].pick].trust;
+         // pick up the actual core package to install
+         if (package[i].type == TY_CYGWIN || package[i].type == TY_NATIVE
+             && xemacs_package == 0)
+           xemacs_package = &package[i];
+         break;
+
+       case TRUST_UNINSTALL:
+         package[i].action = ACTION_UNINSTALL;
+         break;
+
+       case TRUST_KEEP:
+       case TRUST_NONE:
+       default:
+         package[i].action = ACTION_SAME;
+         break;
+       }
+    }
+
+  log (LOG_BABBLE, "Chooser results...");
+  for (i=0; i<npackages; i++)
+    {
+      static char *infos[] = {"prev", "curr", "test"};
+      const char *trust = ((package[i].trust == TRUST_PREV) ? "prev"
+                          : (package[i].trust == TRUST_CURR) ? "curr"
+                          : (package[i].trust == TRUST_TEST) ? "test"
+                          : "unknown");
+      const char *action = ((package[i].action == ACTION_UNKNOWN) ? "unknown"
+                           : (package[i].action == ACTION_SAME) ? "same"
+                           : (package[i].action == ACTION_NEW) ? "new"
+                           : (package[i].action == ACTION_UPGRADE) ? "upgrade"
+                           : (package[i].action == ACTION_UNINSTALL) ? "uninstall"
+                           : (package[i].action == ACTION_ERROR) ? "error"
+                           : "unknown");
+
+      log (LOG_BABBLE, "[%s] action=%s trust=%s src? %s", package[i].name, action, trust,
+          package[i].srcaction == SRCACTION_NO ? "no" : "yes");
+      for (int t=0; t<NTRUST; t++)
+       {
+         if (package[i].info[t].install)
+           log (LOG_BABBLE, "[%s] ver %s inst %s %d src %s %d",
+                infos[t],
+                package[i].info[t].version ? package[i].info[t].version : "(none)",
+                package[i].info[t].install ? package[i].info[t].install : "(none)",
+                package[i].info[t].install_size,
+                package[i].info[t].source ? package[i].info[t].source : "(none)",
+                package[i].info[t].source_size);
+       }
+    }
+}
diff --git a/netinstall/concat.cc b/netinstall/concat.cc
new file mode 100644 (file)
index 0000000..fa86522
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * 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>
+ *
+ */
+
+/* See concat.h.  Note that we canonicalize the result, this avoids
+   multiple slashes being interpreted as UNCs. */
+
+#include "win32.h"
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+char * CDECL
+concat (char *s, ...)
+{
+  int len;
+  char *rv, *arg;
+  va_list v;
+
+  if (!s)
+    return 0;
+
+  len = strlen (s);
+
+  va_start (v, s);
+  while (1)
+    {
+      arg = va_arg (v, char *);
+      if (arg == 0)
+       break;
+      len += strlen (arg);
+    }
+  va_end (v);
+
+  rv = (char *) malloc (len+1);
+  strcpy (rv, s);
+  va_start (v, s);
+  while (1)
+  {
+    arg = va_arg (v, char *);
+    if (arg == 0)
+      break;
+    strcat (rv, arg);
+  }
+  va_end (v);
+
+  /* concat is only used for urls and files, so we can safely
+     canonicalize the results */
+  char *d;
+  for (s=rv; *s; s++)
+    if (*s == '\\')
+      *s = '/';
+  for (s=d=rv; *s; s++)
+    {
+      *d++ = *s;
+      /* special case for URLs */
+      if (*s == ':' && s[1] == '/' && s[2] == '/' && s > rv+1)
+       {
+         *d++ = *++s;
+         *d++ = *++s;
+       }
+      else if (*s == '/')
+       while (s[1] == '/')
+         s++;
+    }
+  *d = 0;
+
+  return rv;
+}
+
+char *
+backslash (char *s)
+{
+  for (char *t = s; *t; t++)
+    if (*t == '/')
+      *t = '\\';
+  return s;
+}
diff --git a/netinstall/concat.h b/netinstall/concat.h
new file mode 100644 (file)
index 0000000..59ca6a5
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * 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>
+ *
+ */
+
+/* Pass a null-terminated list of strings, and it concatenates them
+   into a single string.  Warning - it assumes the result is a file
+   name or URL, and will canonicalize the result accordingly
+   (i.e. replace \ with /, collapse multiple /// to a single /, etc.)  */
+
+char * CDECL concat (char *s, ...);
+
+/* convert slashes to backslashes */
+
+char * backslash (char *s);
diff --git a/netinstall/desktop.cc b/netinstall/desktop.cc
new file mode 100644 (file)
index 0000000..0a7c993
--- /dev/null
@@ -0,0 +1,438 @@
+/*
+ * 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 manage all the desktop setup, such
+   as start menu, batch files, desktop icons, and shortcuts.  Note
+   that unlike other do_* functions, this one is called directly from
+   install.cc */
+
+
+#include "win32.h"
+#include <shlobj.h>
+
+#include <io.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifndef WIN32_NATIVE
+#include <unistd.h>
+#endif
+
+#include "resource.h"
+#include "ini.h"
+#include "msg.h"
+#include "state.h"
+#include "concat.h"
+#include "mkdir.h"
+#include "dialog.h"
+#include "version.h"
+#include "reginfo.h"
+#include "regedit.h"
+#include "port.h"
+
+extern "C" {
+  void make_link_2 (char *exepath, char *args, char *icon, char *lname);
+};
+
+static OSVERSIONINFO verinfo;
+
+/* Lines starting with '@' are conditionals - include 'N' for NT,
+   '5' for Win95, '8' for Win98, '*' for all, like this:
+       echo foo
+       @N8
+       echo NT or 98
+       @*
+   */
+
+#define COMMAND9XARGS "/E:4096 /c"
+#define COMMAND9XEXE  "\\command.com"
+
+static char *iconname;
+static char *batname;
+
+static void
+make_link (char *linkpath, char *title, char *target)
+{
+  char argbuf[_MAX_PATH];
+  char *fname = concat (linkpath, "/", title, ".lnk", 0);
+
+  if (_access (fname, 0) == 0)
+    return; /* already exists */
+
+  msg ("make_link %s, %s, %s\n", fname, title, target);
+
+  mkdir_p (0, fname);
+
+  char *exepath, *args;
+
+  /* If we are running Win9x, build a command line. */
+  if (verinfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
+    {
+      exepath = target;
+      args = "";
+    }
+  else
+    {
+      char windir[MAX_PATH];
+
+      GetWindowsDirectory (windir, sizeof (windir));
+      exepath = concat (windir, COMMAND9XEXE, 0);
+      sprintf (argbuf, "%s %s", COMMAND9XARGS, target);
+      args = argbuf;
+    }
+
+  msg ("make_link_2 (%s, %s, %s, %s)", exepath, args, iconname, fname);
+  make_link_2 (exepath, args, iconname, fname);
+}
+
+static char* 
+find_xemacs_exe_path ()
+{
+  if (xemacs_package->type == TY_CYGWIN)
+    return backslash (concat (root_dir, "/bin/", XEMACS_CYGWIN_ARCH_NAME, 0));
+  else
+    return backslash (concat (root_dir, "\\XEmacs-",
+                             xemacs_package->info[xemacs_package->trust].version, 
+                             "\\", XEMACS_NATIVE_ARCH_NAME, 0));
+}
+
+static char* 
+find_xemacs_exe_name ()
+{
+  if (xemacs_package->type == TY_CYGWIN)
+    return backslash (concat ("xemacs-",
+                             xemacs_package->info[xemacs_package->trust].version, 
+                             ".exe", 0));
+  else
+    return strdup ("xemacs.exe");
+}
+
+static void
+start_menu (char *title, char *target)
+{
+  char path[_MAX_PATH];
+  LPITEMIDLIST id;
+  int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
+  SHGetSpecialFolderLocation (NULL, issystem ? CSIDL_COMMON_PROGRAMS : CSIDL_PROGRAMS, &id);
+  SHGetPathFromIDList (id, path);
+// following lines added because it appears Win95 does not use common programs
+// unless it comes into play when multiple users for Win95 is enabled
+  msg("Program directory for program link: %s",path);
+  if ( strlen(path) == 0) {
+     SHGetSpecialFolderLocation (NULL, CSIDL_PROGRAMS, &id);
+     SHGetPathFromIDList (id, path);
+     msg("Program directory for program link changed to: %s",path);
+  }
+// end of Win95 addition
+  strcat (path, "/");
+  strcat (path, XEMACS_INFO_XEMACS_ORG_REGISTRY_NAME);
+  make_link (path, title, target);
+}
+
+static void
+desktop_icon (char *title, char *target)
+{
+  char path[_MAX_PATH];
+  LPITEMIDLIST id;
+  int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
+  //SHGetSpecialFolderLocation (NULL, issystem ? CSIDL_DESKTOP : CSIDL_COMMON_DESKTOPDIRECTORY, &id);
+  SHGetSpecialFolderLocation (NULL, issystem ? CSIDL_COMMON_DESKTOPDIRECTORY : CSIDL_DESKTOPDIRECTORY, &id);
+  SHGetPathFromIDList (id, path);
+// following lines added because it appears Win95 does not use common programs
+// unless it comes into play when multiple users for Win95 is enabled
+  msg("Desktop directory for desktop link: %s",path);
+  if ( strlen(path) == 0) {
+     SHGetSpecialFolderLocation (NULL, CSIDL_DESKTOPDIRECTORY, &id);
+     SHGetPathFromIDList (id, path);
+     msg("Desktop directory for deskop link changed to: %s",path);
+  }
+// end of Win95 addition
+  make_link (path, title, target);
+}
+
+static int
+uexists (char *path)
+{
+  char *f = concat (root_dir, path, 0);
+  int a = _access (f, 0);
+  free (f);
+  if (a == 0)
+    return 1;
+  return 0;
+}
+
+static void
+make_passwd_group ()
+{
+  if (verinfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
+    {
+      int i;
+
+      LOOP_PACKAGES
+       {
+         if (!strcmp (package[i].name, "cygwin"))
+           {
+             /* mkpasswd and mkgroup are not working on 9x/ME up to 1.1.5-4 */
+             char *border_version = canonicalize_version ("1.1.5-4");
+             char *inst_version = canonicalize_version (pi.version);
+
+             if (strcmp (inst_version, border_version) <= 0)
+               return;
+
+             break;
+           }
+       }
+    }
+
+  if (uexists ("/etc/passwd") && uexists ("/etc/group"))
+    return;
+
+  char *fname = concat (root_dir, "/etc/postinstall/passwd-grp.bat", 0);
+  mkdir_p (0, fname);
+
+  FILE *p = fopen (fname, "wb");
+  if (!p)
+    return;
+
+  if (!uexists ("/etc/passwd"))
+    fprintf (p, "bin\\mkpasswd -l > etc\\passwd\n");
+  if (!uexists ("/etc/group"))
+    fprintf (p, "bin\\mkgroup -l > etc\\group\n");
+
+  fclose (p);
+}
+
+static void
+save_icon ()
+{
+  iconname = backslash (concat (root_dir, XEMACS_RESOURCE_DIR, 
+                               "xemacs.ico", 0));
+
+  HRSRC rsrc = FindResource (NULL, "XEMACS.ICON", "FILE");
+  if (rsrc == NULL)
+    {
+      fatal ("FindResource failed");
+    }
+  HGLOBAL res = LoadResource (NULL, rsrc);
+  char *data = (char *) LockResource (res);
+  int len = SizeofResource (NULL, rsrc);
+
+  FILE *f = fopen (iconname, "wb");
+  if (f)
+    {
+      fwrite (data, 1, len, f);
+      fclose (f);
+    }
+}
+
+static void
+do_desktop_setup()
+{
+  save_icon ();
+
+  if (root_menu && batname) {
+    start_menu ("XEmacs", batname);
+  }
+
+  if (root_desktop && batname) {
+    desktop_icon ("XEmacs", batname);
+  }
+
+  // set regkeys for the application
+  if (xemacs_package != 0)
+    {
+      int issystem = (root_scope == IDC_ROOT_SYSTEM ? 1 : 0);
+      if (xemacs_package->type == TY_NATIVE)
+       {
+#define FROB(exe)        set_app_path ((exe), \
+                       find_xemacs_exe_path (), \
+                       issystem)
+         FROB (find_xemacs_exe_name ());
+         FROB ("runemacs.exe");
+         FROB ("xemacs.exe");
+#undef FROB
+       }
+      else if (xemacs_package->type == TY_CYGWIN)
+       {
+         int junk;
+         char* root = find_cygwin_root (&junk);
+#define FROB(exe)      set_app_path ((exe), \
+                       concat (find_xemacs_exe_path (), ";", \
+                               root, "\\bin;", \
+                               root, "\\usr\\bin", 0), \
+                       issystem)
+         FROB (find_xemacs_exe_name ());
+         FROB ("runemacs.exe");
+         FROB ("xemacs.exe");
+#undef FROB
+       }
+    }
+}
+
+static int da[] = { IDC_ROOT_DESKTOP, 0 };
+static int ma[] = { IDC_ROOT_MENU, 0 };
+
+static void
+check_if_enable_next (HWND h)
+{
+  EnableWindow (GetDlgItem (h, IDOK), 1);
+}
+
+static void
+load_dialog (HWND h)
+{
+  rbset (h, da, root_desktop);
+  rbset (h, ma, root_menu);
+  check_if_enable_next (h);
+}
+
+static int check_desktop (char *title, char *target)
+{
+  char path[_MAX_PATH];
+  LPITEMIDLIST id;
+  int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
+  SHGetSpecialFolderLocation (NULL, issystem ? CSIDL_COMMON_DESKTOPDIRECTORY : CSIDL_DESKTOPDIRECTORY, &id);
+  SHGetPathFromIDList (id, path);
+  // following lines added because it appears Win95 does not use common programs
+  // unless it comes into play when multiple users for Win95 is enabled
+  msg ("Desktop directory for desktop link: %s",path);
+  if (strlen (path) == 0) {
+     SHGetSpecialFolderLocation (NULL, CSIDL_DESKTOPDIRECTORY, &id);
+     SHGetPathFromIDList (id, path);
+     msg ("Desktop directory for deskop link changed to: %s",path);
+  }
+  // end of Win95 addition
+  char *fname = concat (path, "/", title, ".lnk", 0);
+
+  if (_access (fname, 0) == 0)
+    return 0; /* already exists */
+  
+  fname = concat (path, "/", title, ".pif", 0); /* check for a pif as well */
+  
+  if (_access (fname, 0) == 0)
+    return 0; /* already exists */
+
+  return IDC_ROOT_DESKTOP;
+}
+
+static int check_startmenu (char *title, char *target)
+{
+  char path[_MAX_PATH];
+  LPITEMIDLIST id;
+  int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
+  SHGetSpecialFolderLocation (NULL, issystem ? CSIDL_COMMON_PROGRAMS : CSIDL_PROGRAMS, &id);
+  SHGetPathFromIDList (id, path);
+  // following lines added because it appears Win95 does not use common programs
+  // unless it comes into play when multiple users for Win95 is enabled
+  msg ("Program directory for program link: %s",path);
+  if (strlen (path) == 0) {
+     SHGetSpecialFolderLocation (NULL, CSIDL_PROGRAMS, &id);
+     SHGetPathFromIDList (id, path);
+     msg ("Program directory for program link changed to: %s",path);
+  }
+  // end of Win95 addition
+  strcat (path, "/");
+  strcat (path, XEMACS_INFO_XEMACS_ORG_REGISTRY_NAME);
+  char *fname = concat (path, "/", title, ".lnk", 0);
+
+  if (_access (fname, 0) == 0)
+    return 0; /* already exists */
+  
+  fname = concat (path, "/", title, ".pif", 0); /* check for a pif as well */
+  
+  if (_access (fname, 0) == 0)
+    return 0; /* already exists */
+  
+  return IDC_ROOT_MENU;
+}
+
+static void
+save_dialog (HWND h)
+{
+  root_desktop= rbget (h, da);
+  root_menu = rbget (h, ma);
+}
+
+static BOOL
+dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
+{
+  switch (id)
+    {
+
+    case IDC_ROOT_DESKTOP:
+    case IDC_ROOT_MENU:
+      save_dialog (h);
+      check_if_enable_next (h);
+      break;
+
+    case IDOK:
+      save_dialog (h);
+      do_desktop_setup();
+      NEXT (IDD_S_POSTINSTALL);
+      break;
+
+    case IDC_BACK:
+      save_dialog (h);
+      NEXT (IDD_CHOOSE);
+      break;
+
+    case IDCANCEL:
+      NEXT (0);
+      break;
+    }
+  return FALSE;
+}
+
+static BOOL CALLBACK
+dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  switch (message)
+    {
+    case WM_INITDIALOG:
+      load_dialog (h);
+      return FALSE;
+    case WM_COMMAND:
+      return HANDLE_WM_COMMAND (h, wParam, lParam, dialog_cmd);
+    }
+  return FALSE;
+}
+
+void
+do_desktop (HINSTANCE h)
+{
+  CoInitialize (NULL);
+
+  verinfo.dwOSVersionInfoSize = sizeof (verinfo);
+  GetVersionEx (&verinfo);
+  batname = 0;
+
+  if (xemacs_package != 0 && xemacs_package->type != TY_GENERIC)
+    {
+      batname = concat (find_xemacs_exe_path (), "\\",
+                       find_xemacs_exe_name (), 0);
+      root_desktop = check_desktop ("XEmacs", batname);
+      root_menu = check_startmenu ("XEmacs", batname);
+    }
+  else
+    {
+      root_desktop = 0;
+      root_menu = 0;
+    }
+  
+  int rv = 0;
+
+  rv = DialogBox (h, MAKEINTRESOURCE (IDD_DESKTOP), 0, dialog_proc);
+  if (rv == -1)
+    fatal (IDS_DIALOG_FAILED);
+}
diff --git a/netinstall/dialog.cc b/netinstall/dialog.cc
new file mode 100644 (file)
index 0000000..43bedd5
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * 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 provide common functionality for
+   all the dialogs in the program. */
+
+#include "win32.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "dialog.h"
+#include "msg.h"
+#include "log.h"
+
+char *
+eget (HWND h, int id, char *var)
+{
+  char tmp[4000];
+  if (var)
+    {
+      free (var);
+      var = 0;
+    }
+  if (GetDlgItemText (h, id, tmp, sizeof (tmp)) > 0) 
+    {
+      var = (char *) malloc (strlen (tmp)+1);
+      strcpy (var, tmp);
+    }
+  return var;
+}
+
+int
+eget (HWND h, int id)
+{
+  BOOL s;
+  int r = GetDlgItemInt (h, id, &s, TRUE);
+  return r;
+}
+
+void
+eset (HWND h, int id, char *val)
+{
+  SetDlgItemText (h, id, val);
+}
+
+void
+eset (HWND h, int id, int val)
+{
+  SetDlgItemInt (h, id, (UINT)val, TRUE);
+}
+
+int
+rbget (HWND h, int *ids)
+{
+  int i;
+  for (i=0; ids[i]; i++)
+    if (IsDlgButtonChecked (h, ids[i]) == BST_CHECKED)
+      return ids[i];
+  return 0;
+}
+
+void
+rbset (HWND h, int *ids, int id)
+{
+  int i;
+  for (i=0; ids[i]; i++)
+    CheckDlgButton (h, ids[i], id==ids[i] ? BST_CHECKED : BST_UNCHECKED);
+}
+
+void
+fatal (char *m)
+{
+  DWORD e = GetLastError ();
+  char *buf;
+  FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+                0,
+                e,
+                0,
+                (CHAR *)&buf,
+                0,
+                0);
+  MessageBox (0, buf, m, 0);
+  exit_setup (1);
+}
diff --git a/netinstall/dialog.h b/netinstall/dialog.h
new file mode 100644 (file)
index 0000000..44c6f9c
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * 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>
+ *
+ */
+
+/* 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;
+
+/* either "nothing to do" or "setup complete" or something like that */
+extern int exit_msg;
+
+#define D(x) void x(HINSTANCE _h)
+
+/* prototypes for all the do_* functions (most called by main.cc) */
+
+D(do_choose);
+D(do_desktop);
+D(do_download);
+D(do_fromcwd);
+D(do_ini);
+D(do_install);
+D(do_local_dir);
+D(do_net);
+D(do_other);
+D(do_postinstall);
+D(do_root);
+D(do_site);
+D(do_source);
+D(do_splash);
+
+#undef D
+
+/* end this dialog and select the next.  Pass 0 to exit the program */
+#define NEXT(id) EndDialog((HWND)h, 0), next_dialog = id
+
+/* Get the value of an EditText control.  Pass the previously stored
+   value and it will free the memory if needed. */
+char *eget (HWND h, int id, char *var);
+
+/* Same, but convert the value to an integer */
+
+int   eget (HWND h, int id);
+
+/* Set the EditText control to the given string or integer */
+
+void  eset (HWND h, int id, char *var);
+void  eset (HWND h, int id, int var);
+
+/* RadioButtons.  ids is a null-terminated list of IDs.  Get
+   returns the selected ID (or zero), pass an ID to set */
+
+int   rbget (HWND h, int *ids);
+void  rbset (HWND h, int *ids, int id);
+
+/* *This* version of fatal (compare with msg.h) uses GetLastError() to
+   format a suitable error message.  Similar to perror() */
+
+void fatal (char *msg);
diff --git a/netinstall/diskfull.cc b/netinstall/diskfull.cc
new file mode 100644 (file)
index 0000000..3b8961d
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * 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 hide the mess needed just to figure
+   out how full a given disk is.  There is an old API that can't
+   handle disks bigger than 2G, and a new API that isn't always
+   available. */
+
+#include "win32.h"
+#include "diskfull.h"
+
+typedef   BOOL (WINAPI * GDFS)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER,
+                             PULARGE_INTEGER);
+
+int
+diskfull (char *path)
+{
+  GDFS gdfs = 0;
+
+  HINSTANCE k = LoadLibrary ("KERNEL32.DLL");
+  if (k)
+    {
+      gdfs = (GDFS) GetProcAddress (k, "GetDiskFreeSpaceExA");
+
+      if (gdfs)
+       {
+         ULARGE_INTEGER avail, total, free;
+         if (gdfs (path, &avail, &total, &free))
+           {
+             int perc = avail.QuadPart * 100 / total.QuadPart;
+             return 100-perc;
+           }
+       }
+    }
+
+  char root[4];
+  if (path[1] != ':')
+    return 0;
+
+  root[0] = path[0];
+  root[1] = ':';
+  root[2] = '\\';
+  root[3] = 0;
+
+  DWORD junk, free_clusters, total_clusters;
+
+  if (GetDiskFreeSpace (root, &junk, &junk, &free_clusters, &total_clusters))
+    {
+      int perc = free_clusters * 100 / total_clusters;
+      return 100-perc;
+    }
+
+  return 0;
+}
diff --git a/netinstall/diskfull.h b/netinstall/diskfull.h
new file mode 100644 (file)
index 0000000..e198a74
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * 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>
+ *
+ */
+
+/* returns 0..100 (percent) */
+int diskfull (char *path);
diff --git a/netinstall/download.cc b/netinstall/download.cc
new file mode 100644 (file)
index 0000000..3b6ad95
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * 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 download all the files we need to
+   do the installation. */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "win32.h"
+
+#include "resource.h"
+#include "msg.h"
+#include "ini.h"
+#include "dialog.h"
+#include "concat.h"
+#include "geturl.h"
+#include "state.h"
+#include "mkdir.h"
+#include "log.h"
+
+#define pi (package[i].info[package[i].trust])
+
+static int
+download_one (char *name, int expected_size)
+{
+  char *local = name;
+
+  struct stat s;
+  if (stat (local, &s) >= 0)
+    if (s.st_size == expected_size)
+      return 0;
+
+  mkdir_p (0, local);
+
+  if (get_url_to_file (concat (MIRROR_SITE, "/", name, 0),
+                      concat (local, ".tmp", 0),
+                      expected_size))
+    {
+      note (IDS_DOWNLOAD_FAILED, name);
+      return 1;
+    }
+  else
+    {
+      stat (concat (local, ".tmp", 0), &s);
+      if (s.st_size == expected_size)
+       {
+         log (0, "Downloaded %s", local);
+         rename (concat (local, ".tmp", 0), local);
+       }
+      else
+       {
+         log (0, "Download %s wrong size (%d actual vs %d expected)",
+              local, s.st_size, expected_size);
+         note (IDS_DOWNLOAD_SHORT, local, s.st_size, expected_size);
+         return 1;
+       }
+    }
+
+  return 0;
+}
+
+void
+do_download (HINSTANCE h)
+{
+  int i;
+  int errors = 0;
+
+  for (i=0; i<npackages; i++)
+    if (package[i].action == ACTION_NEW || package[i].action == ACTION_UPGRADE)
+      {
+       int e = download_one (pi.install, pi.install_size);
+       if (package[i].srcaction == SRCACTION_YES && pi.source)
+         e += download_one (pi.source, pi.source_size);
+       errors += e;
+       if (e)
+         package[i].action = ACTION_ERROR;
+      }
+
+  dismiss_url_status_dialog ();
+
+  if (errors)
+    {
+      if (yesno (IDS_DOWNLOAD_INCOMPLETE) == IDYES)
+       {
+         next_dialog = IDD_SITE;
+         return;
+       }
+    }
+
+  if (source == IDC_SOURCE_DOWNLOAD)
+    {
+      if (errors)
+       exit_msg = IDS_DOWNLOAD_INCOMPLETE;
+      else
+       exit_msg = IDS_DOWNLOAD_COMPLETE;
+      next_dialog = 0;
+    }
+  else
+    next_dialog = IDD_S_INSTALL;
+}
diff --git a/netinstall/find.cc b/netinstall/find.cc
new file mode 100644 (file)
index 0000000..dfaef53
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * 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 doa recursive find on a given
+   directory, calling a given function for each file found. */
+
+#include "win32.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "port.h"
+
+static void (*for_each)(char *, unsigned int);
+static char dir[_MAX_PATH], *found_part;
+
+static int
+find_sub ()
+{
+  WIN32_FIND_DATA wfd;
+  HANDLE h;
+  char *end = dir + strlen (dir);
+  int rv = 0;
+
+  *end++ = '/';
+  strcpy (end, "*");
+
+  h = FindFirstFile (dir, &wfd);
+
+  if (h == INVALID_HANDLE_VALUE)
+    return 0;
+
+  do {
+    if (strcmp (wfd.cFileName, ".") == 0
+       || strcmp (wfd.cFileName, "..") == 0)
+      continue;
+
+    strcpy (end, wfd.cFileName);
+
+    if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+      find_sub ();
+    else
+      {
+       for_each (found_part, wfd.nFileSizeLow);
+       rv ++;
+      }
+
+  } while (FindNextFile (h, &wfd));
+
+  FindClose (h);
+  return rv;
+}
+
+int
+find (char *starting_dir, void (*_for_each)(char *, unsigned int))
+{
+  strcpy (dir, starting_dir);
+  for_each = _for_each;
+  found_part = dir + strlen (dir) + 1;
+
+  return find_sub ();
+}
diff --git a/netinstall/find.h b/netinstall/find.h
new file mode 100644 (file)
index 0000000..4c38913
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * 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 for_each function is called once for each file found in the
+   starting_dir or any subdir (recursively), passing the relative path
+   (i.e. it doesn't include "starting_dir") and the size of the file
+   (bytes).  find() returns the number of files found.  Directories
+   are scanned but not included in the "found" files. */
+
+extern int find (char *starting_dir, void (*for_each)(char *, unsigned int));
diff --git a/netinstall/fromcwd.cc b/netinstall/fromcwd.cc
new file mode 100644 (file)
index 0000000..0fadb7b
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * 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 handle the case where we're
+   installing from files that already exist in the current directory.
+   If a setup.ini file is present, we set the mirror site to "." and
+   pretend we're installing from the `internet' ;-) else we have to
+   find all the .tar.gz files, deduce their versions, and try to
+   compare versions in the case where the current directory contains
+   multiple versions of any given package.  We do *not* try to compare
+   versions with already installed packages; we always choose a
+   package in the current directory over one that's already installed
+   (otherwise, why would you have asked to install it?).  Note
+   that we search recursively. */
+
+#include "win32.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <io.h>
+#include <ctype.h>
+#ifndef WIN32_NATIVE
+#include <unistd.h>
+#endif
+
+#include "ini.h"
+#include "resource.h"
+#include "concat.h"
+#include "state.h"
+#include "dialog.h"
+#include "msg.h"
+#include "find.h"
+#include "version.h"
+
+#include "port.h"
+
+static int
+is_test_version (char *v)
+{
+  int i;
+  for (i=0; v[i] && isdigit (v[i]); i++) ;
+  return (i >= 6) ? 1 : 0;
+}
+
+char *
+canonicalize_version (char *v)
+{
+  static char nv[3][100];
+  static int idx = 0;
+  char *np, *dp;
+  int i;
+
+  idx = (idx+1) % 3;
+  np = nv[idx];
+
+  while (*v)
+    {
+      if (isdigit (*v))
+       {
+         for (dp=v; *dp && isdigit (*dp); dp++) ;
+         for (i=dp-v; i<12; i++)
+           *np++ = '0';
+         while (v < dp)
+           *np++ = *v++;
+       }
+      else
+       *np++ = *v++;
+    }
+  *np++ = 0;
+  return nv[idx];
+}
+
+static void
+found_file (char *path, unsigned int fsize)
+{
+  char base[_MAX_PATH], *ver;
+
+  int l = strlen (path);
+
+  if (strcmp (path + l - 7, ".tar.gz") != 0)
+    return;
+  if (strstr (path, "-src."))
+    return;
+  if (strstr (path, "-patch."))
+    return;
+
+  char *sl = strrchr (path, '/');
+  if (sl)
+    sl ++;
+  else
+    sl = path;
+  strcpy (base, sl);
+  base[strlen (base) - 7] = 0; /* remove .tar.gz */
+  for (ver=base; *ver; ver++)
+    if ((*ver == '-' || *ver == '_') && isdigit (ver[1]))
+      {
+       *ver++ = 0;
+       break;
+      }
+
+  Package *p = 0;
+  int i;
+
+  for (i=0; i<npackages; i++)
+    if (strcmp (package[i].name, base) == 0)
+      {
+       p = package + i;
+       break;
+      }
+  if (p == 0)
+      p = new_package (strdup (base));
+
+  int trust = is_test_version (ver) ? TRUST_TEST : TRUST_CURR;
+  if (!*ver)
+    trust = TRUST_PREV;
+
+  /* See if this version is older than what we have */
+  if (p->info[trust].version)
+    {
+      char *ov = canonicalize_version (p->info[trust].version);
+      char *nv = canonicalize_version (ver);
+      if (strcmp (ov, nv) > 0)
+       return;
+    }
+
+  l = strlen (base);
+  if (l >= 5 && strcmp (base + l - 5, "win32") == 0)
+    p->type = TY_NATIVE;
+  if (l >= 8 && strcmp (base + l - 8, "cygwin32") == 0)
+    p->type = TY_CYGWIN;
+
+  p->info[trust].version = strdup (ver);
+  p->info[trust].install = strdup (path);
+  p->info[trust].install_size = fsize;
+}
+
+void
+do_fromcwd (HINSTANCE h)
+{
+  if (_access ("./setup.ini", 0) == 0)
+    {
+      mirror_site = ".";
+      next_dialog = IDD_S_LOAD_INI;
+      return;
+    }
+
+  next_dialog = IDD_CHOOSE;
+
+  find (".", found_file);
+
+  // Now see about source tarballs
+  int i, t;
+  Package *p;
+  char srcpath[_MAX_PATH];
+  for (i=0; i<npackages; i++)
+    {
+      p = package+i;
+      for (t=TRUST_PREV; t<=TRUST_TEST; t++)
+       if (p->info[t].install)
+         {
+           strcpy (srcpath, p->info[t].install);
+           strcpy (srcpath + strlen (srcpath) - 7, "-src.tar.gz");
+           msg ("looking for %s", srcpath);
+
+           WIN32_FIND_DATA wfd;
+           HANDLE h = FindFirstFile (srcpath, &wfd);
+           if (h != INVALID_HANDLE_VALUE)
+             {
+               msg("-- got it");
+               FindClose (h);
+               p->info[t].source = strdup (srcpath);
+               p->info[t].source_size = wfd.nFileSizeLow;
+             }
+         }
+    }
+
+  return;
+}
diff --git a/netinstall/geturl.cc b/netinstall/geturl.cc
new file mode 100644 (file)
index 0000000..864319f
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * 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 act as a pretty interface to
+   netio.cc.  We add a progress dialog and some convenience functions
+   (like collect to string or file */
+
+#include "win32.h"
+#include "commctrl.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "dialog.h"
+#include "geturl.h"
+#include "resource.h"
+#include "netio.h"
+#include "msg.h"
+#include "log.h"
+
+static int is_showing = 0;
+static HWND gw_dialog = 0;
+static HWND gw_url = 0;
+static HWND gw_rate = 0;
+static HWND gw_progress = 0;
+static HANDLE init_event;
+static int max_bytes = 0;
+
+static BOOL
+dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
+{
+  switch (id)
+    {
+    case IDCANCEL:
+      exit_setup (0);
+    }
+  return FALSE;
+}
+
+static BOOL CALLBACK
+dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  switch (message)
+    {
+    case WM_INITDIALOG:
+      gw_dialog = h;
+      gw_url = GetDlgItem (h, IDC_DLS_URL);
+      gw_rate = GetDlgItem (h, IDC_DLS_RATE);
+      gw_progress = GetDlgItem (h, IDC_DLS_PROGRESS);
+      SetEvent (init_event);
+      return FALSE;
+    case WM_COMMAND:
+      return HANDLE_WM_COMMAND (h, wParam, lParam, dialog_cmd);
+    }
+  return FALSE;
+}
+
+static DWORD WINAPI
+dialog (void *)
+{
+  MSG m;
+  HWND gw_dialog = CreateDialog (hinstance, MAKEINTRESOURCE (IDD_DLSTATUS),
+                                  0, dialog_proc);
+  ShowWindow (gw_dialog, SW_SHOWNORMAL);
+  UpdateWindow (gw_dialog);
+  while (GetMessage (&m, 0, 0, 0) > 0) {
+    TranslateMessage (&m);
+    DispatchMessage (&m);
+  }
+  return FALSE;
+}
+
+static DWORD start_tics;
+
+static void
+init_dialog (char *url, int length)
+{
+  if (gw_dialog == 0)
+    {
+      DWORD tid;
+      HANDLE thread;
+      init_event = CreateEvent (0, 0, 0, 0);
+      thread = CreateThread (0, 0, dialog, 0, 0, &tid);
+      WaitForSingleObject (init_event, 1000);
+      CloseHandle (init_event);
+      SendMessage (gw_progress, PBM_SETRANGE, 0, MAKELPARAM (0, 100));
+      is_showing = 0;
+    }
+  char *sl=url, *cp;
+  for (cp=url; *cp; cp++)
+    if (*cp == '/' || *cp == '\\' || *cp == ':')
+      sl = cp+1;
+  max_bytes = length;
+  SetWindowText (gw_url, sl);
+  SetWindowText (gw_rate, "Connecting...");
+  SendMessage (gw_progress, PBM_SETPOS, (WPARAM) 0, 0);
+  ShowWindow (gw_progress, (length > 0) ? SW_SHOW : SW_HIDE);
+  ShowWindow (gw_dialog, SW_SHOWNORMAL);
+  if (!is_showing)
+    {
+      SetForegroundWindow (gw_dialog);
+      is_showing = 1;
+    }
+  start_tics = GetTickCount ();
+}
+
+
+static void
+progress (int bytes)
+{
+  static char buf[100];
+  int kbps;
+  static DWORD 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 = bytes / (tics - start_tics);
+  ShowWindow (gw_progress, (max_bytes > 0) ? SW_SHOW : SW_HIDE);
+  if (max_bytes > 100)
+    {
+      int perc = bytes / (max_bytes / 100);
+      SendMessage (gw_progress, PBM_SETPOS, (WPARAM) perc, 0);
+      sprintf (buf, "%3d %%  (%dk/%dk)  %d kb/s\n",
+              perc, bytes/1000, max_bytes/1000, kbps);
+    }
+  else
+    sprintf (buf, "%d  %d kb/s\n", bytes, kbps);
+
+  SetWindowText (gw_rate, buf);
+}
+
+struct GUBuf {
+  GUBuf *next;
+  int count;
+  char buf[2000];
+};
+
+char *
+get_url_to_string (char *_url)
+{
+  log (LOG_BABBLE, "get_url_to_string %s", _url);
+  init_dialog (_url, 0);
+  NetIO *n = NetIO::open (_url);
+  if (!n || !n->ok ())
+    {
+      delete n;
+      log (LOG_BABBLE, "get_url_to_string failed!");
+      return 0;
+    }
+
+  if (n->file_size)
+    max_bytes = n->file_size;
+
+  GUBuf *bufs = 0;
+  GUBuf **nextp = &bufs;
+  int total_bytes = 1; /* for the NUL */
+  progress (0);
+  while (1)
+    {
+      GUBuf *b = new GUBuf;
+      *nextp = b;
+      b->next = 0;
+      nextp = &(b->next);
+
+      b->count = n->read (b->buf, sizeof (b->buf));
+      if (b->count <= 0)
+       break;
+      total_bytes += b->count;
+      progress (total_bytes);
+    }
+
+  char *rv = (char *) malloc (total_bytes);
+  char *rvp = rv;
+  while (bufs && bufs->count > 0)
+    {
+      GUBuf *tmp = bufs->next;
+      memcpy (rvp, bufs->buf, bufs->count);
+      rvp += bufs->count;
+      delete bufs;
+      bufs = tmp;
+    }
+  *rvp = 0;
+  return rv;
+}
+
+int
+get_url_to_file (char *_url, char *_filename, int expected_length)
+{
+  log (LOG_BABBLE, "get_url_to_file %s %s", _url, _filename);
+  init_dialog (_url, expected_length);
+
+  remove (_filename); /* but ignore errors */
+
+  NetIO *n = NetIO::open (_url);
+  if (!n || !n->ok ())
+    {
+      delete n;
+      log (LOG_BABBLE, "get_url_to_file failed!");
+      return 1;
+    }
+
+  FILE *f = fopen (_filename, "wb");
+  if (!f)
+    {
+      char *err = strerror (errno);
+      if (!err)
+       err = "(unknown error)";
+      fatal (IDS_ERR_OPEN_WRITE, _filename, err);
+    }
+
+  if (n->file_size)
+    max_bytes = n->file_size;
+
+  int total_bytes = 0;
+  progress (0);
+  while (1)
+    {
+      char buf[8192];
+      int count;
+      count = n->read (buf, sizeof (buf));
+      if (count <= 0)
+       break;
+      fwrite (buf, 1, count, f);
+      total_bytes += count;
+      progress (total_bytes);
+    }
+
+  fclose (f);
+
+  return 0;
+}
+
+void
+dismiss_url_status_dialog ()
+{
+  ShowWindow (gw_dialog, SW_HIDE);
+  is_showing = 0;
+}
diff --git a/netinstall/geturl.h b/netinstall/geturl.h
new file mode 100644 (file)
index 0000000..32a7b3d
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * 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>
+ *
+ */
+
+/* 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 */
+
+char  *get_url_to_string (char *_url);
+int    get_url_to_file (char *_url, char *_filename, int expected_size);
+void   dismiss_url_status_dialog ();
diff --git a/netinstall/gnu.bmp b/netinstall/gnu.bmp
new file mode 100644 (file)
index 0000000..f6d56f9
Binary files /dev/null and b/netinstall/gnu.bmp differ
diff --git a/netinstall/hash.cc b/netinstall/hash.cc
new file mode 100644 (file)
index 0000000..01a110e
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * 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>
+ *
+ */
+
+/* Simple hash class for install.cc */
+
+#include "win32.h"
+#include <stdlib.h>
+#include <string.h>
+
+#include "hash.h"
+
+class hash_internals {
+public:
+  char **keys;
+  int numkeys;
+  int maxkeys;
+  int prev_index;
+};
+
+hash::hash ()
+{
+  h = new hash_internals;
+  h->numkeys = 0;
+  h->maxkeys = 10;
+  h->keys = (char **) malloc (h->maxkeys * sizeof (char *));
+  h->prev_index = 0;
+}
+
+hash::~hash ()
+{
+  free (h->keys);
+  free (h);
+}
+
+
+void
+hash::add (char *string)
+{
+  int i;
+  for (i=0; i<h->numkeys; i++)
+    if (strcmp (h->keys[i], string) == 0)
+      return;
+  if (h->numkeys >= h->maxkeys)
+    {
+      h->maxkeys += 10;
+      h->keys = (char **) realloc (h->keys, h->maxkeys * sizeof (char *));
+    }
+
+  h->keys[h->numkeys] = _strdup (string);
+  h->numkeys ++;
+}
+
+
+int
+hash::has (char *string)
+{
+  int i;
+  for (i=0; i<h->numkeys; i++)
+    if (strcmp (h->keys[i], string) == 0)
+      return 1;
+  return 0;
+}
+
+char *
+hash::enumerate (char *prev)
+{
+  if (prev == 0)
+    h->prev_index = -1;
+  h->prev_index ++;
+  if (h->prev_index >= h->numkeys)
+    return 0;
+  return h->keys[h->prev_index];
+}
+
+static int CDECL
+rev_len (const void *va, const void *vb)
+{
+  char *a = *(char **)va;
+  char *b = *(char **)vb;
+  return strcmp (b, a);
+}
+
+void
+hash::reverse_sort ()
+{
+  qsort (h->keys, h->numkeys, sizeof (h->keys[0]), rev_len);
+}
diff --git a/netinstall/hash.h b/netinstall/hash.h
new file mode 100644 (file)
index 0000000..2f5407a
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * 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>
+ *
+ */
+
+/* Simple hash class for install.cc */
+
+class hash_internals;
+
+class hash {
+  hash_internals *h;
+ public:
+  hash ();
+  ~hash ();
+
+  void add (char *string);
+  int has (char *string);
+
+  /* specialty for install.cc */
+  void add_subdirs (char *path);
+  void reverse_sort ();
+
+  char *enumerate (char *prev=0);
+};
diff --git a/netinstall/ini.cc b/netinstall/ini.cc
new file mode 100644 (file)
index 0000000..cd2a847
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * 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 get and parse the setup.ini file
+   from the mirror site.  A few support routines for the bison and
+   flex parsers are provided also.  We check to see if this setup.ini
+   is older than the one we used last time, and if so, warn the user. */
+
+#include "win32.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "ini.h"
+#include "resource.h"
+#include "concat.h"
+#include "state.h"
+#include "geturl.h"
+#include "dialog.h"
+#include "msg.h"
+#include "mkdir.h"
+#include "log.h"
+#include "reginfo.h"
+#include "version.h"
+
+unsigned int setup_timestamp = 0;
+char *setup_version = 0;
+
+extern "C" int yyparse ();
+/*extern int yydebug;*/
+
+static char *error_buf = 0;
+static int error_count = 0;
+
+void
+do_ini (HINSTANCE h)
+{
+  char *ini_file = get_url_to_string (concat (MIRROR_SITE, "/setup.ini", 0));
+  dismiss_url_status_dialog ();
+
+  if (!ini_file)
+    {
+      note (IDS_SETUPINI_MISSING, MIRROR_SITE);
+      next_dialog = IDD_SITE;
+      return;
+    }
+
+  package = 0;
+  npackages = 0;
+  setup_timestamp = 0;
+  setup_version = 0;
+
+  ini_init (ini_file);
+
+  setup_timestamp = 0;
+  /*yydebug = 1;*/
+
+  if (yyparse () || error_count > 0)
+    {
+      if (error_count == 1)
+       MessageBox (0, error_buf, "Parse Error", 0);
+      else
+       MessageBox (0, error_buf, "Parse Errors", 0);
+    }
+  else
+    {
+      /* save known-good setup.ini locally */
+      FILE *inif = fopen ("setup.ini", "wb");
+      if (inif)
+       {
+         fwrite (ini_file, 1, strlen (ini_file), inif);
+         fclose (inif);
+       }
+    }
+
+  if (root_dir)
+    {
+      mkdir_p (1, concat (root_dir, XEMACS_SETUP_DIR, 0));
+
+      unsigned int old_timestamp = 0;
+      FILE *ots = fopen (concat (root_dir, XEMACS_SETUP_DIR, "timestamp", 0), "rt");
+      if (ots)
+       {
+         fscanf (ots, "%u", &old_timestamp);
+         fclose (ots);
+         if (old_timestamp && setup_timestamp
+             && (old_timestamp > setup_timestamp))
+           {
+             int yn = yesno (IDS_OLD_SETUPINI);
+             if (yn == IDNO)
+               exit_setup (1);
+           }
+       }
+      if (setup_timestamp)
+       {
+         FILE *nts = fopen (concat (root_dir, XEMACS_SETUP_DIR, "timestamp", 0), "wt");
+         if (nts)
+           {
+             fprintf (nts, "%u", setup_timestamp);
+             fclose (nts);
+           }
+       }
+    }
+
+  msg ("setup_version is %s, our_version is %s", setup_version? setup_version : "(null)", version);
+  if (setup_version)
+    {
+      char *ini_version = canonicalize_version (setup_version);
+      char *our_version = canonicalize_version (version);
+      if (strcmp (our_version, ini_version) < 0)
+       note (IDS_OLD_SETUP_VERSION, version, setup_version);
+    }
+
+  next_dialog = IDD_CHOOSE;
+}
+
+extern "C" int yylineno;
+
+extern "C" int CDECL yyerror (char *s, ...)
+{
+  char buf[1000];
+  int len;
+  sprintf (buf, "setup.ini line %d: ", yylineno);
+  va_list args;
+  va_start (args, s);
+  vsprintf (buf + strlen (buf), s, args);
+  OutputDebugString (buf);
+  if (error_buf)
+    {
+      strcat (error_buf, "\n");
+      len = strlen (error_buf) + strlen (buf) + 5;
+      error_buf = (char *) realloc (error_buf, len);
+      strcat (error_buf, buf);
+    }
+  else
+    {
+      len = strlen (buf) + 5;
+      error_buf = (char *) malloc (len);
+      strcpy (error_buf, buf);
+    }
+  error_count++;
+  return 0;
+}
+
+extern "C" int CDECL fprintf (FILE *f, const char *s, ...);
+
+static char stderrbuf[1000];
+
+int CDECL
+fprintf (FILE *f, const char *fmt, ...)
+{
+  char buf[1000];
+  int rv;
+  va_list args;
+  va_start (args, fmt);
+  if (f == stderr)
+    {
+      rv = vsprintf (buf, fmt, args);
+      strcat (stderrbuf, buf);
+      if (char *nl = strchr (stderrbuf, '\n'))
+       {
+         *nl = 0;
+         /*OutputDebugString (stderrbuf);*/
+         MessageBox (0, buf, "XEmacs Setup", 0);
+         stderrbuf[0] = 0;
+       }
+      
+    }
+  else
+    {
+      rv = vfprintf (f, fmt, args);
+    }
+  return rv;
+}
diff --git a/netinstall/ini.h b/netinstall/ini.h
new file mode 100644 (file)
index 0000000..6e5eab2
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * 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>
+ *
+ */
+
+/* When setup.ini is parsed, the information is stored according to
+   the declarations here.  ini.cc (via inilex and iniparse)
+   initializes these structures.  choose.cc sets the action and trust
+   fields.  download.cc downloads any needed files for selected
+   packages (the chosen "install" field).  install.cc installs
+   selected packages. */
+
+#define YYSTYPE char *
+
+/* lowest number must be most trusted, highest least trusted */
+#define TRUST_PREV             0
+#define TRUST_CURR             1
+#define TRUST_TEST             2
+#define NTRUST 3
+#define TRUST_UNKNOWN          3 /* intentionally not in NTRUST */
+
+#define TY_GENERIC             0
+#define TY_CYGWIN              1
+#define TY_NATIVE              2
+
+#define ACTION_UNKNOWN         0
+#define ACTION_SAME            1
+#define ACTION_NEW             2
+#define ACTION_UPGRADE         3
+#define ACTION_UNINSTALL       4
+#define ACTION_ERROR           5
+
+#define SRCACTION_NO           0
+#define SRCACTION_YES          1
+
+typedef struct {
+  char *name;  /* package name, like "cygwin" */
+  char *sdesc; /* short description (replaces "name" if provided) */
+  char *ldesc; /* long description (multi-line) */
+  int action;  /* ACTION_* - only NEW and UPGRADE get installed */
+  int srcaction;/* SRCACTION_ */
+  int trust;   /* TRUST_* (selects among info[] below) */
+  int type;    /* TY_GENERIC, TY_CYGWIN or TY_NATIVE. */
+
+  struct {
+    char *version;     /* version part of filename */
+    char *install;     /* file name to install */
+    int install_size;  /* in bytes */
+    char *source;      /* sources for installed binaries */
+    int source_size;   /* in bytes */
+  } info[NTRUST+1];    /* +1 for TRUST_UNKNOWN */
+} Package;
+
+extern Package *package;
+extern Package *xemacs_package;
+
+extern int npackages;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+Package *new_package (char *name);
+void   ini_init (char *string);
+
+#define pi (package[i].info[package[i].trust])
+
+#define LOOP_PACKAGES \
+  for (i=0; i<npackages; i++) \
+    if ((package[i].action == ACTION_NEW \
+        || package[i].action == ACTION_UPGRADE) \
+       && pi.install)
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/netinstall/inilex.l b/netinstall/inilex.l
new file mode 100644 (file)
index 0000000..61573ff
--- /dev/null
@@ -0,0 +1,119 @@
+%{
+/*
+ * 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>
+ *
+ */
+
+/* tokenize the setup.ini files.  We parse a string which we've
+   previously downloaded.  The program must call ini_init() to specify
+   that string. */
+
+#include "win32.h"
+#include <string.h>
+#include <stdlib.h>
+
+#include "ini.h"
+#include "iniparse.h"
+
+#define YY_INPUT(buf,result,max_size) { result = ini_getchar(buf, max_size); }
+
+static int ini_getchar(char *buf, int max_size);
+static void ignore_line ();
+
+%}
+
+/*%option debug */
+%option noyywrap
+%option yylineno
+%option never-interactive
+
+STR    [a-zA-Z0-9_./-]+
+
+%%
+
+\"[^"]*\"              { yylval = strdup (yytext+1);
+                         yylval[strlen (yylval)-1] = 0;
+                         return STRING; }
+
+"setup-timestamp:"     return SETUP_TIMESTAMP;
+"setup-version:"       return SETUP_VERSION;
+"version:"             return VERSION;
+"install:"             return INSTALL;
+"type:"                        return TYPE;
+"source:"              return SOURCE;
+"sdesc:"               return SDESC;
+"ldesc:"               return LDESC;
+
+^{STR}":"              ignore_line ();
+
+"[curr]"               return T_CURR;
+"[test]"               return T_TEST;
+"[exp]"                        return T_TEST;
+"[prev]"               return T_PREV;
+"["{STR}"]"            return T_UNKNOWN;
+
+{STR}                  { yylval = strdup (yytext);
+                         return STRING; }
+
+[ \t\r]+               /* do nothing */
+
+"#".*\n                        /* ignore comments */
+
+\n                     { return yytext[0]; }
+.                      { return yytext[0]; }
+
+%%
+
+static char *input_string = 0;
+static char *end_input_string;
+
+void
+ini_init(char *string)
+{
+  input_string = string;
+  end_input_string = input_string + strlen(input_string);
+}
+
+static int
+ini_getchar(char *buf, int max_size)
+{
+  if (input_string)
+    {
+      int avail = end_input_string - input_string;
+      if (avail == 0)
+       {
+         input_string = end_input_string = 0;
+         return 0;
+       }
+      if (avail > max_size)
+       avail = max_size;
+      memcpy(buf, input_string, avail);
+      input_string += avail;
+      return avail;
+    }
+  else
+    return 0;
+}
+
+static void
+ignore_line ()
+{
+  char c;
+  while (c = input ())
+    {
+      if (c == EOF)
+       return;
+      if (c == '\n')
+       return;
+    }
+}
diff --git a/netinstall/iniparse.h b/netinstall/iniparse.h
new file mode 100644 (file)
index 0000000..d8b2c85
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef YYSTYPE
+#define YYSTYPE int
+#endif
+#define        STRING  257
+#define        SETUP_TIMESTAMP 258
+#define        SETUP_VERSION   259
+#define        VERSION 260
+#define        INSTALL 261
+#define        SOURCE  262
+#define        SDESC   263
+#define        LDESC   264
+#define        TYPE    265
+#define        T_PREV  266
+#define        T_CURR  267
+#define        T_TEST  268
+#define        T_UNKNOWN       269
+
+
+extern YYSTYPE yylval;
diff --git a/netinstall/iniparse.y b/netinstall/iniparse.y
new file mode 100644 (file)
index 0000000..1e78486
--- /dev/null
@@ -0,0 +1,134 @@
+%{
+/*
+ * 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>
+ *
+ */
+
+/* Parse the setup.ini files.  inilex.l provides the tokens for this. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "win32.h"
+
+#include "ini.h"
+#include "iniparse.h"
+
+#include "port.h"
+
+#define YYERROR_VERBOSE 1
+/*#define YYDEBUG 1*/
+
+static Package *cp;
+static int trust;
+extern unsigned int setup_timestamp;
+extern char *setup_version;
+extern int yylineno;
+extern int CDECL yyerror (char *s, ...);
+
+#define cpt (cp->info+trust)
+
+%}
+
+%token STRING
+%token SETUP_TIMESTAMP SETUP_VERSION VERSION INSTALL SOURCE SDESC LDESC TYPE
+%token T_PREV T_CURR T_TEST T_UNKNOWN
+
+%%
+
+whole_file
+ : setup_headers packages
+ ;
+
+setup_headers
+ : setup_header setup_headers
+ | /* empty */
+ ;
+
+setup_header
+ : SETUP_TIMESTAMP STRING '\n' { setup_timestamp = strtoul ($2, 0, 0); }
+ | SETUP_VERSION STRING '\n' { setup_version = strdup ($2); }
+ | '\n'
+ | error { yyerror ("unrecognized line in setup.ini headers (do you have the latest setup?)"); } '\n'
+ ;
+
+packages
+ : package packages
+ | /* empty */
+ ;
+
+package
+ : '@' STRING '\n'             { new_package($2); }
+   lines
+ ;
+
+lines
+ : simple_line '\n' lines
+ | simple_line
+ ;
+
+simple_line
+ : VERSION STRING              { cpt->version = $2; }
+ | SDESC STRING                        { cp->sdesc = $2; }
+ | LDESC STRING                        { cp->ldesc = $2; }
+ | INSTALL STRING STRING       { cpt->install = $2;
+                                 cpt->install_size = atoi($3); }
+ | SOURCE STRING STRING                { cpt->source = $2;
+                                 cpt->source_size = atoi($3); }
+ | TYPE STRING         { if (!strcmp ($2, "cygwin"))
+                                       cp->type = TY_CYGWIN;
+                                 else if (!strcmp ($2, "native"))
+                                       cp->type = TY_NATIVE;
+                                 else 
+                                       cp->type = TY_GENERIC; }
+ | T_PREV                      { trust = TRUST_PREV; }
+ | T_CURR                      { trust = TRUST_CURR; }
+ | T_TEST                      { trust = TRUST_TEST; }
+ | T_UNKNOWN                   { trust = TRUST_UNKNOWN; }
+ | /* empty */
+ | error '\n' { yylineno --;
+               yyerror ("unrecognized line in package %s (do you have the latest setup?)", cp->name);
+               yylineno ++;
+             }
+ ;
+
+%%
+
+Package *package = 0;
+Package *xemacs_package = 0;
+int npackages = 0;
+static int maxpackages = 0;
+
+Package *
+new_package (char *name)
+{
+  if (package == 0)
+    maxpackages = npackages = 0;
+  if (npackages >= maxpackages)
+    {
+      maxpackages += 10;
+      if (package)
+       package = (Package *) realloc (package, maxpackages * sizeof (Package));
+      else
+       package = (Package *) malloc (maxpackages * sizeof (Package));
+    }
+  cp = package + npackages;
+  npackages ++;
+
+  memset (cp, 0, sizeof (Package));
+  cp->name = name;
+
+  trust = TRUST_CURR;
+
+  return cp;
+}
diff --git a/netinstall/install.cc b/netinstall/install.cc
new file mode 100644 (file)
index 0000000..5d64055
--- /dev/null
@@ -0,0 +1,491 @@
+/*
+ * 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>
+#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"
+
+static HWND ins_dialog = 0;
+static HWND ins_action = 0;
+static HWND ins_pkgname = 0;
+static HWND ins_filename = 0;
+static HWND ins_pprogress = 0;
+static HWND ins_iprogress = 0;
+static HWND ins_diskfull = 0;
+static HANDLE init_event;
+
+static int total_bytes = 0;
+static int total_bytes_sofar = 0;
+static int package_bytes = 0;
+
+static BOOL
+dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
+{
+  switch (id)
+    {
+    case IDCANCEL:
+      exit_setup (1);
+    }
+  return FALSE;
+}
+
+static BOOL CALLBACK
+dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  switch (message)
+    {
+    case WM_INITDIALOG:
+      ins_dialog = h;
+      ins_action = GetDlgItem (h, IDC_INS_ACTION);
+      ins_pkgname = GetDlgItem (h, IDC_INS_PKG);
+      ins_filename = GetDlgItem (h, IDC_INS_FILE);
+      ins_pprogress = GetDlgItem (h, IDC_INS_PPROGRESS);
+      ins_iprogress = GetDlgItem (h, IDC_INS_IPROGRESS);
+      ins_diskfull = GetDlgItem (h, IDC_INS_DISKFULL);
+      SetEvent (init_event);
+      return FALSE;
+    case WM_COMMAND:
+      return HANDLE_WM_COMMAND (h, wParam, lParam, dialog_cmd);
+    }
+  return FALSE;
+}
+
+static DWORD WINAPI
+dialog (void *)
+{
+  MSG m;
+  HWND new_dialog = CreateDialog (hinstance, MAKEINTRESOURCE (IDD_INSTATUS),
+                                  0, dialog_proc);
+  if (new_dialog == 0)
+    fatal ("create dialog");
+  ShowWindow (new_dialog, SW_SHOWNORMAL);
+  UpdateWindow (new_dialog);
+  while (GetMessage (&m, 0, 0, 0) > 0) {
+    TranslateMessage (&m);
+    DispatchMessage (&m);
+  }
+  return FALSE;
+}
+
+static void
+init_dialog ()
+{
+  if (ins_dialog == 0)
+    {
+      DWORD tid;
+      HANDLE thread;
+      init_event = CreateEvent (0, 0, 0, 0);
+      thread = CreateThread (0, 0, dialog, 0, 0, &tid);
+      WaitForSingleObject (init_event, 10000);
+      CloseHandle (init_event);
+      SendMessage (ins_pprogress, PBM_SETRANGE, 0, MAKELPARAM (0, 100));
+      SendMessage (ins_iprogress, PBM_SETRANGE, 0, MAKELPARAM (0, 100));
+      SendMessage (ins_diskfull, PBM_SETRANGE, 0, MAKELPARAM (0, 100));
+    }
+
+  SetWindowText (ins_pkgname, "");
+  SetWindowText (ins_filename, "");
+  SendMessage (ins_pprogress, PBM_SETPOS, (WPARAM) 0, 0);
+  SendMessage (ins_iprogress, PBM_SETPOS, (WPARAM) 0, 0);
+  SendMessage (ins_diskfull, PBM_SETPOS, (WPARAM) 0, 0);
+  ShowWindow (ins_dialog, SW_SHOWNORMAL);
+  SetForegroundWindow (ins_dialog);
+}
+
+static void
+progress (int bytes)
+{
+  int perc;
+
+  if (package_bytes > 100)
+    {
+      perc = bytes / (package_bytes / 100);
+      SendMessage (ins_pprogress, PBM_SETPOS, (WPARAM) perc, 0);
+    }
+
+  if (total_bytes > 100)
+    {
+      perc = (total_bytes_sofar + bytes) / (total_bytes / 100);
+      SendMessage (ins_iprogress, PBM_SETPOS, (WPARAM) perc, 0);
+    }
+}
+
+static void
+badrename (char *o, char *n)
+{
+  char *err = strerror (errno);
+  if (!err)
+    err = "(unknown error)";
+  note (IDS_ERR_RENAME, o, n, err);
+}
+
+static char *standard_dirs[] = {
+  0
+};
+
+void
+hash::add_subdirs (char *path)
+{
+  char *nonp, *pp;
+  for (nonp = path; *nonp == '\\' || *nonp == '/'; nonp++);
+  for (pp = path + strlen(path) - 1; pp>nonp; pp--)
+    if (*pp == '/' || *pp == '\\')
+      {
+       int i, s=0;
+       char c = *pp;
+       *pp = 0;
+       for (i=0; standard_dirs[i]; i++)
+         if (strcmp (standard_dirs[i]+1, path) == 0)
+           {
+             s = 1;
+             break;
+           }
+       if (s == 0)
+         add (path);
+       *pp = c;
+      }
+}
+
+char *
+map_filename (char *fn, int type)
+{
+  char *dest_file;
+  while (*fn == '/' || *fn == '\\')
+    fn++;
+  if (type == TY_GENERIC)
+    dest_file = concat (root_dir, XEMACS_PACKAGE_DIR, fn, 0);
+  else                         // TY_CYGWIN | TY_NATIVE
+    dest_file = concat (root_dir, "/", fn, 0);
+  return dest_file;
+}
+
+static int
+exists (char *file)
+{
+  if (_access (file, 0) == 0)
+    return 1;
+  return 0;
+}
+
+         
+static int num_installs, num_uninstalls;
+
+static void
+uninstall_one (char *name, int action, int type)
+{
+  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");
+
+  if (lst)
+    {
+      SetWindowText (ins_pkgname, name);
+      SetWindowText (ins_action, "Uninstalling...");
+      if (action == ACTION_UPGRADE)
+       log (0, "Uninstalling old %s", name);
+      else
+       log (0, "Uninstalling %s", name);
+
+      while (fgets (line, sizeof (line), lst))
+       {
+         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 ++;
+    }
+}
+
+         
+static int
+install_one (char *name, char *file, int file_size, int action, int type)
+{
+  int errors = 0;
+  char *local = file, *cp, *fn, *base;
+
+  base = local;
+  for (cp=local; *cp; cp++)
+    if (*cp == '/' || *cp == '\\' || *cp == ':')
+      base = cp+1;
+  SetWindowText (ins_pkgname, base);
+
+  if (!exists (local) && exists (base))
+    local = base;
+  if (!exists (local))
+    {
+      note (IDS_ERR_OPEN_READ, local, "No such file");
+      return 1;
+    }
+
+  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, "wb");
+
+  package_bytes = file_size;
+
+  switch (action)
+    {
+    case ACTION_NEW:
+      SetWindowText (ins_action, "Installing...");
+      break;
+    case ACTION_UPGRADE:
+      SetWindowText (ins_action, "Upgrading...");
+      break;
+    }
+
+  log (0, "Installing %s", local);
+  tar_open (local);
+  while ((fn = tar_next_file ()))
+    {
+      char *dest_file;
+
+      if (lst)
+       fprintf (lst, "%s\n", fn);
+
+      dest_file = map_filename (fn, type);
+
+      SetWindowText (ins_filename, dest_file);
+      log (LOG_BABBLE, "Installing file %s", dest_file);
+      if (tar_read_file (dest_file) != 0)
+       {
+         log (0, "Unable to install file %s", dest_file);
+         errors ++;
+       }
+
+      progress (tar_ftell ());
+      num_installs ++;
+    }
+  tar_close ();
+
+  total_bytes_sofar += file_size;
+  progress (0);
+
+  int df = diskfull (root_dir);
+  SendMessage (ins_diskfull, PBM_SETPOS, (WPARAM) df, 0);
+
+  if (lst)
+    fclose (lst);
+
+  return errors;
+}
+
+void
+do_install (HINSTANCE h)
+{
+  int i;
+  int errors = 0;
+
+  num_installs = 0, num_uninstalls = 0;
+
+  next_dialog = IDD_DESKTOP;
+
+  mkdir_p (1, root_dir);
+
+  for (i=0; standard_dirs[i]; i++)
+    {
+      char *p = concat (root_dir, standard_dirs[i], 0);
+      mkdir_p (1, p);
+      free (p);
+    }
+
+  dismiss_url_status_dialog ();
+
+  init_dialog ();
+
+  total_bytes = 0;
+  total_bytes_sofar = 0;
+
+  int df = diskfull (root_dir);
+  SendMessage (ins_diskfull, PBM_SETPOS, (WPARAM) df, 0);
+
+  LOOP_PACKAGES
+    {
+      total_bytes += pi.install_size;
+    }
+
+  for (i=0; i<npackages; i++)
+    {
+      if (package[i].action == ACTION_UNINSTALL
+         || (package[i].action == ACTION_UPGRADE && pi.install))
+       {
+         uninstall_one (package[i].name, package[i].action,
+                        package[i].type);
+         uninstall_one (concat (package[i].name, "-src", 0), package[i].action,
+                        package[i].type);
+       }
+
+      if ((package[i].action == ACTION_NEW
+          || package[i].action == ACTION_UPGRADE)
+         && pi.install)
+       {
+         int e = install_one (package[i].name, pi.install, pi.install_size, package[i].action,
+                              package[i].type);
+         if (package[i].srcaction == SRCACTION_YES && pi.source)
+           e += install_one (concat (package[i].name, "-src", 0), pi.source, pi.source_size,
+                             package[i].action, package[i].type);
+         if (e)
+           {
+             package[i].action = ACTION_ERROR;
+             errors++;
+           }
+       }
+    } // end of big package loop
+
+  ShowWindow (ins_dialog, SW_HIDE);
+
+  char *odbn = concat (root_dir, XEMACS_SETUP_DIR, "installed.db", 0);
+  char *ndbn = concat (root_dir, XEMACS_SETUP_DIR, "installed.db.new", 0);
+  char *sdbn = concat (root_dir, XEMACS_SETUP_DIR, "installed.db.old", 0);
+
+  mkdir_p (0, ndbn);
+
+  FILE *odb = fopen (odbn, "rt");
+  FILE *ndb = fopen (ndbn, "wb");
+
+  if (!ndb)
+    {
+      char *err = strerror (errno);
+      if (!err)
+       err = "(unknown error)";
+      fatal (IDS_ERR_OPEN_WRITE, ndb, err);
+    }
+
+  if (odb)
+    {
+      char line[1000], pkg[1000];
+      int printit;
+      while (fgets (line, 1000, odb))
+       {
+         printit = 1;
+         sscanf (line, "%s", pkg);
+         for (i=0; i<npackages; i++)
+           {
+             if (strcmp (pkg, package[i].name) == 0)
+               switch (package[i].action)
+                 {
+                 case ACTION_NEW:
+                 case ACTION_UPGRADE:
+                 case ACTION_UNINSTALL:
+                   printit = 0;
+                   break;
+                 }
+           }
+         if (printit)
+           fputs (line, ndb);
+       }
+      
+    }
+
+  LOOP_PACKAGES
+    {
+      if (package[i].srcaction == SRCACTION_YES)
+       fprintf (ndb, "%s %s %d %s %d\n", package[i].name,
+                pi.install, pi.install_size,
+                pi.source, pi.source_size);
+      else
+       fprintf (ndb, "%s %s %d\n", package[i].name,
+                pi.install, pi.install_size);
+    }
+
+  if (odb)
+    fclose (odb);
+  fclose (ndb);
+
+  remove (sdbn);
+  if (odb && rename (odbn, sdbn))
+    badrename (odbn, sdbn);
+
+  remove (odbn);
+  if (rename (ndbn, odbn))
+    badrename (ndbn, odbn);
+
+  if (num_installs == 0 && num_uninstalls == 0)
+    {
+      exit_msg = IDS_NOTHING_INSTALLED;
+      return;
+    }
+  if (num_installs == 0)
+    {
+      exit_msg = IDS_UNINSTALL_COMPLETE;
+      return;
+    }
+
+  if (errors)
+    exit_msg = IDS_INSTALL_INCOMPLETE;
+  else
+    exit_msg = IDS_INSTALL_COMPLETE;
+}
diff --git a/netinstall/localdir.cc b/netinstall/localdir.cc
new file mode 100644 (file)
index 0000000..89f8e34
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * 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 Andrej Borsenkow <Andrej.Borsenkow@mow.siemens.ru>
+ * based on work and suggestions of DJ Delorie
+ *
+ */
+
+/* The purpose of this file is to ask the user where they want the
+   root of the installation to be, and to ask whether the user prefers
+   text or binary mounts. */
+
+#include "win32.h"
+#include <shlobj.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "dialog.h"
+#include "resource.h"
+#include "state.h"
+#include "msg.h"
+#include "concat.h"
+#include "log.h"
+
+static void
+check_if_enable_next (HWND h)
+{
+  EnableWindow (GetDlgItem (h, IDOK), local_dir != 0);
+}
+
+static void
+load_dialog (HWND h)
+{
+  eset (h, IDC_LOCAL_DIR, local_dir);
+  check_if_enable_next (h);
+}
+
+static void
+save_dialog (HWND h)
+{
+  local_dir = eget (h, IDC_LOCAL_DIR, local_dir);
+}
+
+
+static int CALLBACK
+browse_cb (HWND h, UINT m, LPARAM lp, LPARAM data)
+{
+  switch (m)
+    {
+    case BFFM_INITIALIZED:
+      if (local_dir)
+       SendMessage (h, BFFM_SETSELECTION, TRUE, (LPARAM)local_dir);
+      break;
+    }
+  return 0;
+}
+
+static void
+browse (HWND h)
+{
+  BROWSEINFO bi;
+  CHAR name[MAX_PATH];
+  LPITEMIDLIST pidl;
+  memset (&bi, 0, sizeof (bi));
+  bi.hwndOwner = h;
+  bi.pszDisplayName = name;
+  bi.lpszTitle = "Select download directory";
+  bi.ulFlags = BIF_RETURNONLYFSDIRS;
+  bi.lpfn = browse_cb;
+  pidl = SHBrowseForFolder (&bi);
+  if (pidl)
+    {
+      if (SHGetPathFromIDList (pidl, name))
+       eset (h, IDC_LOCAL_DIR, name);
+    }
+}
+
+
+static BOOL
+dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
+{
+  switch (id)
+    {
+
+    case IDC_LOCAL_DIR:
+      save_dialog (h);
+      check_if_enable_next (h);
+      break;
+
+    case IDC_LOCAL_DIR_BROWSE:
+      browse (h);
+      break;
+
+    case IDOK:
+      save_dialog (h);
+      if (SetCurrentDirectoryA (local_dir))
+       {
+         switch (source)
+           {
+           case IDC_SOURCE_DOWNLOAD:
+             NEXT (IDD_NET);
+             break;
+           case IDC_SOURCE_NETINST:
+           case IDC_SOURCE_CWD:
+             NEXT (IDD_ROOT);
+             break;
+           default:
+             NEXT (0);
+             break;
+           }
+       }
+      else
+       note (IDS_ERR_CHDIR, local_dir);
+
+      break;
+
+    case IDC_BACK:
+      save_dialog (h);
+      NEXT (IDD_SOURCE);
+      break;
+
+    case IDCANCEL:
+      NEXT (0);
+      break;
+    }
+  return FALSE;
+}
+
+static BOOL CALLBACK
+dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  switch (message)
+    {
+    case WM_INITDIALOG:
+      load_dialog (h);
+      return FALSE;
+    case WM_COMMAND:
+      return HANDLE_WM_COMMAND (h, wParam, lParam, dialog_cmd);
+    }
+  return FALSE;
+}
+
+extern char cwd[_MAX_PATH];
+
+void
+do_local_dir (HINSTANCE h)
+{
+  int rv = 0;
+  rv = DialogBox (h, MAKEINTRESOURCE (IDD_LOCAL_DIR), 0, dialog_proc);
+  if (rv == -1)
+    fatal (IDS_DIALOG_FAILED);
+
+  log (0, "Selected local directory: %s", local_dir);
+}
+
diff --git a/netinstall/log.cc b/netinstall/log.cc
new file mode 100644 (file)
index 0000000..0ffc8e5
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * 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@redhat.com>
+ *
+ */
+
+/* The purpose of this file is to centralize all the logging functions. */
+
+#include "win32.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "resource.h"
+#include "msg.h"
+#include "log.h"
+#include "dialog.h"
+#include "state.h"
+#include "concat.h"
+#include "mkdir.h"
+
+struct LogEnt {
+  LogEnt *next;
+  int flags;
+  time_t when;
+  char msg[1];
+};
+
+static LogEnt *first_logent = 0;
+static LogEnt **next_logent = &first_logent;
+
+void
+log (int flags, char *fmt, ...)
+{
+  char buf[1000];
+  va_list args;
+  va_start (args, fmt);
+  vsprintf (buf, fmt, args);
+
+  LogEnt *l = (LogEnt *) malloc (sizeof (LogEnt) + strlen (buf) + 20);
+  l->next = 0;
+  l->flags = flags;
+  time (&(l->when));
+  *next_logent = l;
+  next_logent = &(l->next);
+
+  char *b = l->msg;
+  if (flags & LOG_TIMESTAMP)
+    {
+      struct tm *tm = localtime (&(l->when));
+      strftime (b, 1000, "%Y/%m/%d %H:%M:%S ", tm);
+      b += strlen (b);
+    }
+
+  strcpy (b, buf);
+  msg ("LOG: %d %s", l->flags, l->msg);
+}
+
+void
+log_save (int babble, char *filename, int append)
+{
+  static int been_here = 0;
+  if (been_here)
+    return;
+  been_here = 1;
+
+  mkdir_p (0, filename);
+
+  FILE *f = fopen (filename, append ? "at" : "wt");
+  if (!f)
+    {
+      fatal (IDS_NOLOGFILE, filename);
+      return;
+    }
+
+  LogEnt *l;
+
+  for (l=first_logent; l; l=l->next)
+    {
+      if (babble || !(l->flags & LOG_BABBLE))
+       {
+         fputs (l->msg, f);
+         if (l->msg[strlen(l->msg)-1] != '\n')
+           fputc ('\n', f);
+       }
+    }
+
+  fclose (f);
+  been_here = 0;
+}
+
+void
+exit_setup (int exit_code)
+{
+  static int been_here = 0;
+  if (been_here)
+    ExitProcess (1);
+  been_here = 1;
+
+  if (exit_msg)
+    note (exit_msg);
+
+  log (LOG_TIMESTAMP, "Ending cygwin install");
+
+  if (source == IDC_SOURCE_DOWNLOAD || !root_dir)
+    {
+      log_save (LOG_BABBLE, "setup.log.full", 0);
+      log_save (0, "setup.log", 1);
+    }
+  else
+    {
+      log_save (LOG_BABBLE, concat (root_dir, "/setup.log.full", 0), 0);
+      log_save (0, concat (root_dir, "/setup.log", 0), 1);
+    }
+
+  ExitProcess (exit_code);
+}
diff --git a/netinstall/log.h b/netinstall/log.h
new file mode 100644 (file)
index 0000000..40c4b9d
--- /dev/null
@@ -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@redhat.com>
+ *
+ */
+
+/* This is for "printf"-like logging.  Messages are stored in memory
+   until they're written out.  "babble" means the message is just idle
+   babbling; it can be ignored for shorter logs. */
+
+#define LOG_BABBLE     1
+#define LOG_TIMESTAMP  2
+
+void log (int flags, char *fmt, ...);
+
+/* Here, "babble" means to write out the babble also.  If "append" is
+   nonzero, the log is appended to any existing file. */
+
+void log_save (int babble, char *filename, int append);
+
+/* This is the only legal way to exit.  It writes out all the logs and things */
+
+void exit_setup (int exit_code);
diff --git a/netinstall/main.cc b/netinstall/main.cc
new file mode 100644 (file)
index 0000000..4a93fb2
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * 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>
+ *
+ */
+
+/* OK, here's how this works.  Each of the steps needed for install -
+   dialogs, downloads, installs - are in their own files and have some
+   "do_*" function (prototype in dialog.h) and a resource id (IDD_* or
+   IDD_S_* in resource.h) for that step.  Each step is responsible for
+   selecting the next step!  See the NEXT macro in dialog.h.  Note
+   that the IDD_S_* ids are fake; those are for steps that don't
+   really have a controlling dialog (some have progress dialogs, but
+   those don't count, although they could).  Replace the IDD_S_* with
+   IDD_* if you create a real dialog for those steps. */
+
+#include "win32.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "resource.h"
+#include "dialog.h"
+#include "state.h"
+#include "msg.h"
+#include "netio.h"
+#include "find.h"
+#include "log.h"
+
+#include "port.h"
+
+void netio_test (char *);
+
+int next_dialog;
+int exit_msg = 0;
+
+HINSTANCE hinstance;
+
+int WINAPI
+WinMain (HINSTANCE h,
+        HINSTANCE hPrevInstance,
+        LPSTR command_line,
+        int cmd_show)
+{
+  hinstance = h;
+
+  next_dialog = IDD_SPLASH;
+
+  log (LOG_TIMESTAMP, "Starting XEmacs install");
+
+  char cwd[_MAX_PATH];
+  GetCurrentDirectory (sizeof (cwd), cwd);
+  local_dir = strdup (cwd);
+  log (0, "Current Directory: %s", cwd);
+
+  while (next_dialog)
+    {
+      switch (next_dialog)
+       {
+       case IDD_SPLASH:        do_splash (h);  break;
+       case IDD_SOURCE:        do_source (h);  break;
+       case IDD_LOCAL_DIR:     do_local_dir (h); break;
+       case IDD_ROOT:          do_root (h);    break;
+       case IDD_NET:           do_net (h);     break;
+       case IDD_SITE:          do_site (h);    break;
+       case IDD_OTHER_URL:     do_other (h);   break;
+       case IDD_S_LOAD_INI:    do_ini (h);     break;
+       case IDD_S_FROM_CWD:    do_fromcwd (h); break;
+       case IDD_CHOOSE:        do_choose (h);  break;
+       case IDD_S_DOWNLOAD:    do_download (h); break;
+       case IDD_S_INSTALL:     do_install (h); break;
+       case IDD_DESKTOP:       do_desktop (h); break;
+       case IDD_S_POSTINSTALL: do_postinstall (h); break;
+
+       default:
+         next_dialog = 0;
+         break;
+       }
+    }
+
+  exit_setup (0);
+
+  return EXIT_SUCCESS;
+}
diff --git a/netinstall/mkdir.cc b/netinstall/mkdir.cc
new file mode 100644 (file)
index 0000000..ab62f9e
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * 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>
+ *
+ */
+
+/* see mkdir.h */
+
+#include "win32.h"
+#include <stdio.h>
+#include "mkdir.h"
+
+int
+mkdir_p (int isadir, char *path)
+{
+  char saved_char, *slash = 0;
+  char *c;
+  DWORD d, gse;
+
+  d = GetFileAttributes (path);
+  if (d != 0xffffffff && d & FILE_ATTRIBUTE_DIRECTORY)
+    return 0;
+
+  if (isadir)
+    {
+      if (CreateDirectory (path, 0))
+       return 0;
+      gse = GetLastError ();
+      if (gse != ERROR_PATH_NOT_FOUND && gse != ERROR_FILE_NOT_FOUND)
+       {
+         if (gse == ERROR_ALREADY_EXISTS)
+           {
+             fprintf (stderr, "warning: deleting \"%s\" so I can make a directory there\n",
+                      path);
+             if (DeleteFileA (path))
+               return mkdir_p (isadir, path);
+           }
+         return 1;
+       }
+    }
+
+  for (c=path; *c; c++)
+    {
+      if (*c == ':')
+       slash = 0;
+      if (*c == '/' || *c == '\\')
+       slash = c;
+    }
+
+  if (!slash)
+    return 0;
+
+  saved_char = *slash;
+  *slash = 0;
+  if (mkdir_p (1, path))
+    {
+      *slash = saved_char;
+      return 1;
+    }
+  *slash = saved_char;
+
+  if (!isadir)
+    return 0;
+
+  return mkdir_p (isadir, path);
+}
diff --git a/netinstall/mkdir.h b/netinstall/mkdir.h
new file mode 100644 (file)
index 0000000..151edc0
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * 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>
+ *
+ */
+
+/* Create a directory, and any needed parent directories.  If "isadir"
+   is non-zero, "path" is the name of a directory.  If "isadir" is
+   zero, "path" is the name of a *file* that we need a directory
+   for. */
+
+extern int mkdir_p (int isadir, char *path);
diff --git a/netinstall/mklink2.c b/netinstall/mklink2.c
new file mode 100644 (file)
index 0000000..deed33d
--- /dev/null
@@ -0,0 +1,27 @@
+#include "win32.h"
+#include "shlobj.h"
+
+/* This part of the code must be in C because the C++ interface to COM
+doesn't work. */
+
+void
+make_link_2 (char *exepath, char *args, char *icon, char *lname)
+{
+  IShellLink *sl;
+  IPersistFile *pf;
+  WCHAR widepath [_MAX_PATH];
+
+  CoCreateInstance (&CLSID_ShellLink, NULL,
+                   CLSCTX_INPROC_SERVER, &IID_IShellLink, (LPVOID *) & sl);
+  sl->lpVtbl->QueryInterface (sl, &IID_IPersistFile, (void **) &pf);
+
+  sl->lpVtbl->SetPath (sl, exepath);
+  sl->lpVtbl->SetArguments (sl, args);
+  sl->lpVtbl->SetIconLocation (sl, icon, 0);
+
+  MultiByteToWideChar (CP_ACP, 0, lname, -1, widepath, _MAX_PATH);
+  pf->lpVtbl->Save (pf, widepath, TRUE);
+
+  pf->lpVtbl->Release (pf);
+  sl->lpVtbl->Release (sl);
+}
diff --git a/netinstall/msg.cc b/netinstall/msg.cc
new file mode 100644 (file)
index 0000000..5a9ed24
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * 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 centralize all the message
+   functions. */
+
+static char *cvsid = "\n%%% $Id: msg.cc,v 1.1.2.1 2000/12/11 22:01:36 andyp Exp $\n";
+
+#include "win32.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include "dialog.h"
+#include "log.h"
+
+void
+msg (char *fmt, ...)
+{
+  char buf[1000];
+  va_list args;
+  va_start (args, fmt);
+  vsprintf (buf, fmt, args);
+  OutputDebugString (buf);
+}
+
+static int
+mbox (char *name, int type, int id, va_list args)
+{
+  char buf[1000], fmt[1000];
+
+  if (LoadString (hinstance, id, fmt, sizeof (fmt)) <= 0)
+    ExitProcess (0);
+
+  vsprintf (buf, fmt, args);
+  log (0, "mbox %s: %s", name, buf);
+  return MessageBox (0, buf, "XEmacs Setup", type | MB_TOPMOST);
+}
+
+void
+note (int id, ...)
+{
+  va_list args;
+  va_start (args, id);
+  mbox ("note", 0, id, args);
+}
+
+void
+fatal (int id, ...)
+{
+  va_list args;
+  va_start (args, id);
+  mbox ("fatal", 0, id, args);
+  exit_setup (1);
+}
+
+int
+yesno (int id, ...)
+{
+  va_list args;
+  va_start (args, id);
+  return mbox ("yesno", MB_YESNO, id, args);
+}
diff --git a/netinstall/msg.h b/netinstall/msg.h
new file mode 100644 (file)
index 0000000..ddd3785
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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>
+ *
+ */
+
+/* This is for "printf"-like debugging.  Messages go to
+   OutputDebugString, which can be seen while debugging under GDB or
+   via a debug message monitor. */
+
+void msg(char *fmt, ...);
+
+/* This pops up a dialog with text from the string table ("id"), which
+   is interpreted like printf.  The program exits when the user
+   presses OK. */
+
+void fatal (int id, ...);
+
+/* Similar, but the program continues when the user presses OK */
+
+void note (int id, ...);
+
+/* returns IDYES or IDNO, otherwise same as note() */
+int yesno (int id, ...);
diff --git a/netinstall/net.cc b/netinstall/net.cc
new file mode 100644 (file)
index 0000000..3891d3f
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * 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 get the network configuration
+   information from the user. */
+
+#include "win32.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "dialog.h"
+#include "resource.h"
+#include "state.h"
+#include "msg.h"
+#include "log.h"
+
+static int rb[] = { IDC_NET_IE5, IDC_NET_DIRECT, IDC_NET_PROXY, 0 };
+
+static void
+check_if_enable_next (HWND h)
+{
+  int e = 0, p = 0, pu = 0;
+  if (net_method == IDC_NET_IE5)
+    pu = 1;
+  if (net_method == IDC_NET_IE5 || net_method == IDC_NET_DIRECT)
+    e = 1;
+  else if (net_method == IDC_NET_PROXY)
+    {
+      p = pu = 1;
+      if (net_proxy_host && net_proxy_port)
+       e = 1;
+    }
+  EnableWindow (GetDlgItem (h, IDOK), e);
+  EnableWindow (GetDlgItem (h, IDC_PROXY_HOST), p);
+  EnableWindow (GetDlgItem (h, IDC_PROXY_PORT), p);
+}
+
+static void
+load_dialog (HWND h)
+{
+  rbset (h, rb, net_method);
+  eset (h, IDC_PROXY_HOST, net_proxy_host);
+  if (net_proxy_port == 0)
+    net_proxy_port = 80;
+  eset (h, IDC_PROXY_PORT, net_proxy_port);
+  check_if_enable_next (h);
+}
+
+static void
+save_dialog (HWND h)
+{
+  net_method = rbget (h, rb);
+  net_proxy_host = eget (h, IDC_PROXY_HOST, net_proxy_host);
+  net_proxy_port = eget (h, IDC_PROXY_PORT);
+}
+
+static BOOL
+dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
+{
+  switch (id)
+    {
+
+    case IDC_NET_IE5:
+    case IDC_NET_DIRECT:
+    case IDC_NET_PROXY:
+    case IDC_PROXY_HOST:
+    case IDC_PROXY_PORT:
+      save_dialog (h);
+      check_if_enable_next (h);
+      break;
+
+    case IDOK:
+      save_dialog (h);
+      switch (source)
+       {
+       case IDC_SOURCE_NETINST:
+       case IDC_SOURCE_DOWNLOAD:
+         NEXT (IDD_SITE);
+         break;
+       case IDC_SOURCE_CWD:
+         NEXT (0);
+         break;
+       default:
+         msg ("source is default? %d\n", source);
+         NEXT (0);
+       }
+      break;
+
+    case IDC_BACK:
+      save_dialog (h);
+      switch (source)
+       {
+       case IDC_SOURCE_DOWNLOAD:
+         NEXT (IDD_LOCAL_DIR);
+         break;
+       case IDC_SOURCE_NETINST:
+       case IDC_SOURCE_CWD:
+         NEXT (IDD_ROOT);
+         break;
+       }
+      break;
+
+    case IDCANCEL:
+      NEXT (0);
+      break;
+    }
+  return FALSE;
+}
+
+static BOOL CALLBACK
+dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  switch (message)
+    {
+    case WM_INITDIALOG:
+      load_dialog (h);
+      return FALSE;
+    case WM_COMMAND:
+      return HANDLE_WM_COMMAND (h, wParam, lParam, dialog_cmd);
+    }
+  return FALSE;
+}
+
+void
+do_net (HINSTANCE h)
+{
+  int rv = 0;
+
+  rv = DialogBox (h, MAKEINTRESOURCE (IDD_NET), 0, dialog_proc);
+  if (rv == -1)
+    fatal (IDS_DIALOG_FAILED);
+
+  log (0, "net: %s",
+       (net_method == IDC_NET_IE5) ? "IE5" :
+       (net_method == IDC_NET_DIRECT) ? "Direct" : "Proxy");
+}
+
diff --git a/netinstall/netio.cc b/netinstall/netio.cc
new file mode 100644 (file)
index 0000000..5d04d93
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * 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 coordinate the various access
+   methods known to setup.  To add a new method, create a pair of
+   nio-*.[ch] files and add the logic to NetIO::open here */
+
+#include "win32.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "resource.h"
+#include "state.h"
+#include "msg.h"
+#include "netio.h"
+#include "nio-file.h"
+#include "nio-ie5.h"
+#include "nio-http.h"
+#include "nio-ftp.h"
+#include "dialog.h"
+#include "log.h"
+
+#include "port.h"
+
+NetIO::NetIO (char *Purl)
+{
+  set_url (Purl);
+}
+
+NetIO::~NetIO ()
+{
+  if (url)
+    free (url);
+  if (proto)
+    free (proto);
+  if (host)
+    free (host);
+  if (path)
+    free (path);
+}
+
+void
+NetIO::set_url (char *Purl)
+{
+  char *bp, *ep, c;
+
+  file_size = 0;
+  url = _strdup (Purl);
+  proto = 0;
+  host = 0;
+  port = 0;
+  path = 0;
+
+  bp = url;
+  ep = strstr (bp, "://");
+  if (!ep)
+    {
+      path = url;
+      return;
+    }
+
+  *ep = 0;
+  proto = _strdup (bp);
+  *ep = ':';
+  bp = ep+3;
+
+  ep = bp + strcspn (bp, ":/");
+  c = *ep;
+  *ep = 0;
+  host = _strdup (bp);
+  *ep = c;
+
+  if (*ep == ':')
+    {
+      port = atoi (ep+1);
+      ep = strchr (ep, '/');
+    }
+
+  if (*ep)
+    path = _strdup (ep);
+}
+
+int
+NetIO::ok ()
+{
+  return 0;
+}
+
+int
+NetIO::read (char *buf, int nbytes)
+{
+  return 0;
+}
+
+NetIO *
+NetIO::open (char *url)
+{
+  NetIO *rv = 0;
+  enum {http, ftp, file} proto;
+  if (strncmp (url, "http://", 7) == 0)
+    proto = http;
+  else if (strncmp (url, "ftp://", 6) == 0)
+    proto = ftp;
+  else
+    proto = file;
+
+  if (proto == file)
+    rv = new NetIO_File (url);
+  else if (net_method == IDC_NET_IE5)
+    rv = new NetIO_IE5 (url);
+  else if (net_method == IDC_NET_PROXY)
+    rv = new NetIO_HTTP (url);
+  else if (net_method == IDC_NET_DIRECT)
+    {
+      switch (proto)
+       {
+       case http:
+         rv = new NetIO_HTTP (url);
+         break;
+       case ftp:
+         rv = new NetIO_FTP (url);
+         break;
+       }
+    }
+
+  if (!rv->ok ())
+    {
+      delete rv;
+      return 0;
+    }
+
+  return rv;
+}
+
+
+static char **user, **passwd;
+static int loading = 0;
+
+static void
+check_if_enable_ok (HWND h)
+{
+  int e = 0;
+  if (*user && *passwd)
+    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);
+}
+
+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);
+      exit_setup (1);
+      break;
+    }
+  return FALSE;
+}
+
+static BOOL CALLBACK
+auth_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  switch (message)
+    {
+    case WM_INITDIALOG:
+      load_dialog (h);
+      return FALSE;
+    case WM_COMMAND:
+      return HANDLE_WM_COMMAND (h, wParam, lParam, auth_cmd);
+    }
+  return FALSE;
+}
+
+static int
+auth_common (HINSTANCE h, int id)
+{
+  return DialogBox (h, MAKEINTRESOURCE (id), 0, auth_proc);
+}
+
+int
+NetIO::get_auth ()
+{
+  user = &net_user;
+  passwd = &net_passwd;
+  return auth_common (hinstance, IDD_NET_AUTH);
+}
+
+int
+NetIO::get_proxy_auth ()
+{
+  user = &net_proxy_user;
+  passwd = &net_proxy_passwd;
+  return auth_common (hinstance, IDD_PROXY_AUTH);
+}
diff --git a/netinstall/netio.h b/netinstall/netio.h
new file mode 100644 (file)
index 0000000..b0a91ca
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * 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>
+ *
+ */
+
+/* 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:
+  NetIO (char *url);
+  void set_url (char *url);
+
+public:
+  /* if nonzero, this is the estimated total file size */
+  int file_size;
+  /* broken down url FYI */
+  char *url;
+  char *proto;
+  char *host;
+  int port;
+  char *path;
+  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() */
+  static NetIO * open (char *url);
+
+  /* If !ok() that means the transfer isn't happening. */
+  virtual int ok ();
+
+  /* Read `nbytes' bytes from the file.  Returns zero when the file
+     is complete. */
+  virtual int read (char *buf, int nbytes);
+
+  /* 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 ();
+};
diff --git a/netinstall/nio-file.cc b/netinstall/nio-file.cc
new file mode 100644 (file)
index 0000000..57e061d
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * 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 manage access to files stored on the
+   local disk (i.e. "downloading" setup.ini).  Called from netio.cc */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include "win32.h"
+#include "netio.h"
+#include "nio-file.h"
+#include "resource.h"
+#include "msg.h"
+
+NetIO_File::NetIO_File (char *Purl)
+  : NetIO (Purl)
+{
+  struct stat s;
+  fd = fopen (path, "rb");
+  if (fd)
+    {
+      stat (path, &s);
+      file_size = s.st_size;
+    }
+  else
+    {
+      char *err = strerror (errno);
+      if (!err)
+       err = "(unknown error)";
+      note (IDS_ERR_OPEN_READ, path, err);
+    }
+}
+
+NetIO_File::~NetIO_File ()
+{
+  if (fd)
+    fclose ((FILE *)fd);
+}
+
+int
+NetIO_File::ok ()
+{
+  return fd ? 1 : 0;
+}
+
+int
+NetIO_File::read (char *buf, int nbytes)
+{
+  return fread (buf, 1, nbytes, (FILE *)fd);
+}
diff --git a/netinstall/nio-file.h b/netinstall/nio-file.h
new file mode 100644 (file)
index 0000000..6d2eb92
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * 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>
+ *
+ */
+
+/* see nio-file.cc */
+
+class NetIO_File : public NetIO {
+public:
+  NetIO_File (char *url);
+  void *fd;
+  ~NetIO_File ();
+  virtual int ok ();
+  virtual int read (char *buf, int nbytes);
+};
diff --git a/netinstall/nio-ftp.cc b/netinstall/nio-ftp.cc
new file mode 100644 (file)
index 0000000..f30beb6
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * 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>
+ *
+ */
+
+/* This file is responsible for implementing all direct FTP protocol
+   channels.  It is intentionally simplistic. */
+
+#include "win32.h"
+#include "winsock.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "resource.h"
+#include "state.h"
+#include "simpsock.h"
+#include "log.h"
+
+#include "netio.h"
+#include "nio-ftp.h"
+
+static SimpleSocket *cmd = 0;
+static char *cmd_host = 0;
+static int cmd_port = 0;
+
+static char *last_line;
+
+static int
+ftp_line (SimpleSocket *s)
+{
+  do {
+    last_line = s->gets ();
+    log (LOG_BABBLE, "ftp > %s", last_line);
+  } while (last_line && (!isdigit (last_line[0]) || last_line[3] != ' '));
+  return atoi (last_line ? last_line : "0");
+}
+
+NetIO_FTP::NetIO_FTP (char *Purl)
+  : NetIO (Purl)
+{
+  s = 0;
+  int code;
+
+  if (port == 0)
+    port = 21;
+
+  if (cmd_host && strcmp (host, cmd_host) != 0 || port != cmd_port)
+    {
+      if (cmd)
+       cmd->printf ("QUIT\r\n");
+      delete cmd;
+      free (cmd_host);
+      cmd = 0;
+      cmd_host = 0;
+    }
+
+  if (cmd == 0)
+    {
+      SimpleSocket *c = new SimpleSocket (host, port);
+      code = ftp_line (c);
+      c->printf ("USER anonymous\r\n");
+      code = ftp_line (c);
+      if (code == 331)
+       {
+         c->printf ("PASS cygwin-setup@\r\n");
+         code = ftp_line (c);
+       }
+
+      if (code < 200 || code >= 300)
+       {
+         delete c;
+         return;
+       }
+
+      cmd = c;
+      cmd_host = _strdup (host);
+      cmd_port = port;
+
+      cmd->printf ("TYPE I\r\n");
+      code = ftp_line (cmd);
+    }
+
+  cmd->printf ("PASV\r\n");
+  do {
+    code = ftp_line (cmd);
+  } while (code == 226); /* previous RETR */
+  if (code != 227)
+    return;
+
+  char *paren = strchr (last_line, '(');
+  if (!paren)
+    return;
+
+  int i1, i2, i3, i4, p1, p2;
+  sscanf (paren+1, "%d,%d,%d,%d,%d,%d", &i1, &i2, &i3, &i4, &p1, &p2);
+  char tmp[20];
+  sprintf (tmp, "%d.%d.%d.%d", i1, i2, i3, i4);
+  s = new SimpleSocket (tmp, p1*256 + p2);
+
+  cmd->printf ("RETR %s\r\n", path);
+  code = ftp_line (cmd);
+  if (code != 150)
+    {
+      delete s;
+      s = 0;
+      return;
+    }
+}
+
+NetIO_FTP::~NetIO_FTP ()
+{
+  if (s)
+    delete s;
+}
+
+int
+NetIO_FTP::ok ()
+{
+  if (s)
+    return 1;
+  return 0;
+}
+
+int
+NetIO_FTP::read (char *buf, int nbytes)
+{
+  if (!s)
+    return 0;
+  return s->read (buf, nbytes);
+}
diff --git a/netinstall/nio-ftp.h b/netinstall/nio-ftp.h
new file mode 100644 (file)
index 0000000..4548bcd
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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>
+ *
+ */
+
+/* Direct FTP (without proxy) */
+
+class SimpleSocket;
+
+class NetIO_FTP : public NetIO {
+  SimpleSocket *s;
+
+public:
+  NetIO_FTP (char *url);
+  virtual ~NetIO_FTP ();
+
+  /* If !ok() that means the transfer isn't happening. */
+  virtual int ok ();
+
+  /* Read `nbytes' bytes from the file.  Returns zero when the file
+     is complete. */
+  virtual int read (char *buf, int nbytes);
+};
diff --git a/netinstall/nio-http.cc b/netinstall/nio-http.cc
new file mode 100644 (file)
index 0000000..fa5210a
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * 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>
+ *
+ */
+
+/* This file is responsible for implementing all direct HTTP protocol
+   channels.  It is intentionally simplistic. */
+
+#include "win32.h"
+#include "winsock.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "resource.h"
+#include "state.h"
+#include "simpsock.h"
+#include "msg.h"
+
+#include "netio.h"
+#include "nio-http.h"
+
+static char six2pr[64] = {
+    'A','B','C','D','E','F','G','H','I','J','K','L','M',
+    'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
+    'a','b','c','d','e','f','g','h','i','j','k','l','m',
+    'n','o','p','q','r','s','t','u','v','w','x','y','z',
+    '0','1','2','3','4','5','6','7','8','9','+','/'
+};
+
+static char *
+base64_encode (char *username, char *password)
+{
+  unsigned char *ep;
+  char *rp;
+  static char *rv = 0;
+  if (rv)
+    free (rv);
+  rv = (char *) malloc (2 * (strlen (username) + strlen (password)) + 5);
+
+  char *up = (char *) malloc (strlen (username) + strlen (password) + 6);
+  strcpy (up, username);
+  strcat (up, ":");
+  strcat (up, password);
+  ep = (unsigned char *)up + strlen (up);
+  *ep++ = 0;
+  *ep++ = 0;
+  *ep++ = 0;
+
+  char block[4];
+
+  rp = rv;
+
+  for (ep = (unsigned char *)up; *ep; ep += 3)
+    {
+      block[0] = six2pr[ep[0] >> 2];
+      block[1] = six2pr[((ep[0] << 4) & 0x30) | ((ep[1] >> 4) & 0x0f)];
+      block[2] = six2pr[((ep[1] << 2) & 0x3c) | ((ep[2] >> 6) & 0x03)];
+      block[3] = six2pr[ep[2] & 0x3f];
+
+      if (ep[1] == 0)
+       block[2] = block[3] = '=';
+      if (ep[2] == 0)
+       block[3] = '=';
+      memcpy (rp, block, 4);
+      rp += 4;
+    }
+  *rp = 0;
+
+  free (up);
+
+  return rv;
+}
+
+NetIO_HTTP::NetIO_HTTP (char *Purl)
+  : NetIO (Purl)
+{
+ retry_get:
+  if (port == 0)
+    port = 80;
+
+  if (net_method == IDC_NET_PROXY)
+    s = new SimpleSocket (net_proxy_host, net_proxy_port);
+  else
+    s = new SimpleSocket (host, port);
+
+  if (!s->ok())
+    {
+      s = 0;
+      return;
+    }
+
+  if (net_method == IDC_NET_PROXY)
+    s->printf ("GET %s HTTP/1.0\r\n", url);
+  else
+    s->printf ("GET %s HTTP/1.0\r\n", path);
+  s->printf ("Host: %s:%d\r\n", host, port);
+
+  if (net_user && net_passwd)
+    s->printf ("Authorization: Basic %s\r\n",
+              base64_encode (net_user, net_passwd));
+
+  if (net_proxy_user && net_proxy_passwd)
+    s->printf ("Proxy-Authorization: Basic %s\r\n",
+              base64_encode (net_proxy_user, net_proxy_passwd));
+
+  s->printf ("\r\n");
+
+  char *l = s->gets ();
+  int code;
+  sscanf (l, "%*s %d", &code);
+  if (code >= 300 && code < 400)
+    {
+      do {
+       l = s->gets ();
+       if (_strnicmp (l, "Location:", 9) == 0)
+         {
+           char *u = l + 9;
+           while (*u == ' ' || *u == '\t')
+             u++;
+           set_url (u);
+           delete s;
+           goto retry_get;
+         }
+      } while (*l);
+    }
+  if (code == 401) /* authorization required */
+    {
+      get_auth ();
+      delete s;
+      goto retry_get;
+    }
+  if (code == 407) /* proxy authorization required */
+    {
+      get_proxy_auth ();
+      delete s;
+      goto retry_get;
+    }
+  if (code >= 300)
+    {
+      delete s;
+      s = 0;
+      return;
+    }
+  do {
+    l = s->gets ();
+    if (_strnicmp (l, "Content-Length:", 15) == 0)
+      sscanf (l, "%*s %d", &file_size);
+  } while (*l);
+}
+
+NetIO_HTTP::~NetIO_HTTP ()
+{
+  if (s)
+    delete s;
+}
+
+int
+NetIO_HTTP::ok ()
+{
+  if (s)
+    return 1;
+  return 0;
+}
+
+int
+NetIO_HTTP::read (char *buf, int nbytes)
+{
+  return s->read (buf, nbytes);
+}
diff --git a/netinstall/nio-http.h b/netinstall/nio-http.h
new file mode 100644 (file)
index 0000000..e634299
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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>
+ *
+ */
+
+/* Direct HTTP (with or without proxy) */
+
+class SimpleSocket;
+
+class NetIO_HTTP : public NetIO {
+  SimpleSocket *s;
+
+public:
+  NetIO_HTTP (char *url);
+  virtual ~NetIO_HTTP ();
+
+  /* If !ok() that means the transfer isn't happening. */
+  virtual int ok ();
+
+  /* Read `nbytes' bytes from the file.  Returns zero when the file
+     is complete. */
+  virtual int read (char *buf, int nbytes);
+};
diff --git a/netinstall/nio-ie5.cc b/netinstall/nio-ie5.cc
new file mode 100644 (file)
index 0000000..9f2cae0
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * 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 manage internet downloads using the
+   Internet Explorer version 5 DLLs.  To use this method, the user
+   must already have installed and configured IE5.  This module is
+   called from netio.cc, which is called from geturl.cc */
+
+static char *cvsid = "\n%%% $Id: nio-ie5.cc,v 1.1.2.1 2000/12/11 22:01:41 andyp Exp $\n";
+
+#include "win32.h"
+
+#include "resource.h"
+#include "state.h"
+#include "dialog.h"
+#include "msg.h"
+#include "netio.h"
+#include "nio-ie5.h"
+
+static HINTERNET internet = 0;
+
+NetIO_IE5::NetIO_IE5 (char *_url)
+  : NetIO (_url)
+{
+  int resend = 0;
+
+  if (internet == 0)
+    {
+      HINSTANCE h = LoadLibrary ("wininet.dll");
+      if (!h)
+       {
+         note (IDS_WININET);
+         connection = 0;
+         return;
+       }
+      InternetAttemptConnect (0);
+      internet = InternetOpen ("Cygwin Setup", INTERNET_OPEN_TYPE_PRECONFIG,
+                              NULL, NULL, 0);
+    }
+
+  DWORD flags =
+    INTERNET_FLAG_DONT_CACHE |
+    INTERNET_FLAG_KEEP_CONNECTION |
+    INTERNET_FLAG_PRAGMA_NOCACHE |
+    INTERNET_FLAG_RELOAD |
+    INTERNET_FLAG_EXISTING_CONNECT |
+    INTERNET_FLAG_PASSIVE;
+
+  connection = InternetOpenUrl (internet, url, NULL, 0, flags, 0);
+
+ try_again:
+
+  if (net_user && net_passwd)
+    {
+      InternetSetOption (connection, INTERNET_OPTION_USERNAME,
+                        net_user, strlen (net_user));
+      InternetSetOption (connection, INTERNET_OPTION_PASSWORD,
+                        net_passwd, strlen (net_passwd));
+    }
+
+  if (net_proxy_user && net_proxy_passwd)
+    {
+      InternetSetOption (connection, INTERNET_OPTION_PROXY_USERNAME,
+                        net_proxy_user, strlen (net_proxy_user));
+      InternetSetOption (connection, INTERNET_OPTION_PROXY_PASSWORD,
+                        net_proxy_passwd, strlen (net_proxy_passwd));
+    }
+
+  if (resend)
+    if (!HttpSendRequest (connection, 0, 0, 0, 0))
+      connection = 0;
+
+  if (!connection)
+    {
+      if (GetLastError () == ERROR_INTERNET_EXTENDED_ERROR)
+       {
+         char buf[2000];
+         DWORD e, l=sizeof (buf);
+         InternetGetLastResponseInfo (&e, buf, &l);
+         MessageBox (0, buf, "Internet Error", 0);
+       }
+    }
+
+  DWORD type, type_s;
+  type_s = sizeof (type);
+  InternetQueryOption (connection, INTERNET_OPTION_HANDLE_TYPE,
+                      &type, &type_s);
+
+  switch (type)
+    {
+    case INTERNET_HANDLE_TYPE_HTTP_REQUEST:
+    case INTERNET_HANDLE_TYPE_CONNECT_HTTP:
+      type_s = sizeof (DWORD);
+      if (HttpQueryInfo (connection,
+                        HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,
+                        &type, &type_s, NULL))
+       {
+         if (type == 401) /* authorization required */
+           {
+             flush_io();
+             get_auth ();
+             resend = 1;
+             goto try_again;
+           }
+         else if (type == 407) /* proxy authorization required */
+           {
+             flush_io();
+             get_proxy_auth ();
+             resend = 1;
+             goto try_again;
+           }
+         else if (type >= 300)
+           {
+             connection = 0;
+             return;
+           }
+       }
+    }
+}
+
+void
+NetIO_IE5::flush_io ()
+{
+  DWORD actual = 0;
+  char buf[1024];
+  do {
+    InternetReadFile (connection, buf, 1024, &actual);
+  } while (actual > 0);
+}
+
+NetIO_IE5::~NetIO_IE5 ()
+{
+  if (connection)
+    InternetCloseHandle (connection);
+}
+
+int
+NetIO_IE5::ok ()
+{
+  return (connection == NULL) ? 0 : 1;
+}
+
+int
+NetIO_IE5::read (char *buf, int nbytes)
+{
+  DWORD actual;
+  if (InternetReadFile (connection, buf, nbytes, &actual))
+    return actual;
+  return -1;
+}
diff --git a/netinstall/nio-ie5.h b/netinstall/nio-ie5.h
new file mode 100644 (file)
index 0000000..4cc71d5
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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>
+ *
+ */
+
+/* see nio-ie5.cc */
+
+class NetIO_IE5 : public NetIO {
+  HINTERNET connection;
+public:
+  NetIO_IE5 (char *url);
+  ~NetIO_IE5 ();
+  virtual int ok ();
+  virtual int read (char *buf, int nbytes);
+  void flush_io();
+};
diff --git a/netinstall/other.cc b/netinstall/other.cc
new file mode 100644 (file)
index 0000000..a701281
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * 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>
+ *
+ */
+
+/* This handles the "other URL" option from the mirror site
+   selection. */
+
+#include "win32.h"
+#include <shlobj.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "dialog.h"
+#include "resource.h"
+#include "state.h"
+#include "msg.h"
+#include "log.h"
+
+/* private shared function, from site.cc */
+void save_site_url (void);
+
+static void
+check_if_enable_next (HWND h)
+{
+  EnableWindow (GetDlgItem (h, IDOK), other_url ? 1 : 0);
+}
+
+static void
+load_dialog (HWND h)
+{
+  eset (h, IDC_OTHER_URL, other_url);
+  check_if_enable_next (h);
+}
+
+static void
+save_dialog (HWND h)
+{
+  other_url = eget (h, IDC_OTHER_URL, other_url);
+}
+
+static BOOL
+dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
+{
+  switch (id)
+    {
+
+    case IDC_OTHER_URL:
+      save_dialog (h);
+      check_if_enable_next (h);
+      break;
+
+    case IDOK:
+      save_dialog (h);
+      save_site_url ();
+      NEXT (IDD_S_LOAD_INI);
+      break;
+
+    case IDC_BACK:
+      save_dialog (h);
+      NEXT (IDD_SITE);
+      break;
+
+    case IDCANCEL:
+      NEXT (0);
+      break;
+    }
+  return FALSE;
+}
+
+static BOOL CALLBACK
+dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  switch (message)
+    {
+    case WM_INITDIALOG:
+      load_dialog (h);
+      return FALSE;
+    case WM_COMMAND:
+      return HANDLE_WM_COMMAND (h, wParam, lParam, dialog_cmd);
+    }
+  return FALSE;
+}
+
+void
+do_other (HINSTANCE h)
+{
+  int rv = 0;
+  rv = DialogBox (h, MAKEINTRESOURCE (IDD_OTHER_URL), 0, dialog_proc);
+  if (rv == -1)
+    fatal (IDS_DIALOG_FAILED);
+
+  log (0, "site: %s", other_url);
+}
+
diff --git a/netinstall/port.h b/netinstall/port.h
new file mode 100644 (file)
index 0000000..c2c019a
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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>
+ *
+ */
+
+/* I prefer building a cygwin version of setup for debugging, as I
+   find that gdb can debug those programs (and the exceptions they
+   cause) better.  This file handles the slight differences between
+   cygwin and mingw. */
+
+#if defined(__CYGWIN__) || defined (__CYGWIN32__)
+
+#define _MAX_PATH MAX_PATH
+
+#define _access access
+#define _strdup strdup
+
+#endif
diff --git a/netinstall/postinstall.cc b/netinstall/postinstall.cc
new file mode 100644 (file)
index 0000000..bf26f66
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * 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 run all the post-install scripts
+   in their various forms. */
+
+#include "win32.h"
+
+#include <io.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifndef WIN32_NATIVE
+#include <unistd.h>
+#endif
+
+#include "state.h"
+#include "dialog.h"
+#include "find.h"
+#include "concat.h"
+#include "regedit.h"
+#include "reginfo.h"
+#include "resource.h"
+#include "port.h"
+
+static char *sh = 0;
+static char *cmd = 0;
+static OSVERSIONINFO verinfo;
+
+static void
+run (char *shscript, char *args, char *file)
+{
+  BOOL b;
+  char cmdline [_MAX_PATH];
+  STARTUPINFO si;
+  PROCESS_INFORMATION pi;
+
+  sprintf (cmdline, "%s %s %s", shscript, args, file);
+  memset (&pi, 0, sizeof (pi));
+  memset (&si, 0, sizeof (si));
+  si.cb = sizeof (si);
+  si.lpTitle = "XEmacs Setup Post-Install Script";
+  si.dwFlags = STARTF_USEPOSITION;
+
+  b = CreateProcess (0, cmdline, 0, 0, 0,
+                    CREATE_NEW_CONSOLE, 0, root_dir, &si, &pi);
+
+  if (b)
+    WaitForSingleObject (pi.hProcess, INFINITE);
+}
+
+static void
+each (char *fname, unsigned int size)
+{
+  char *ext = strrchr (fname, '.');
+  if (!ext)
+    return;
+
+  if (sh && strcmp (ext, ".sh") == 0)
+    {
+      char *f2 = concat (root_dir, XEMACS_SETUP_DIR, "postinstall/", fname, 0);
+      run (sh, "-c", f2);
+      free (f2);
+    }
+  else if (cmd && strcmp (ext, ".bat") == 0)
+    {
+      char *f2 = backslash (concat (root_dir, XEMACS_SETUP_DIR, "postinstall/", 
+                                   fname, 0));
+      run (cmd, "/c", f2);
+      free (f2);
+    }
+  else
+    return;
+
+  rename (concat (root_dir, XEMACS_SETUP_DIR, "postinstall/", fname, 0),
+         concat (root_dir, XEMACS_SETUP_DIR, "postinstall/", fname, ".done", 0));
+}
+
+static char *shells [] = {
+  "/bin/sh.exe",
+  "/usr/bin/sh.exe",
+  "/bin/bash.exe",
+  "/usr/bin/bash.exe",
+  0
+};
+
+void
+do_postinstall (HINSTANCE h)
+{
+  int issystem;
+  next_dialog = 0;
+  char* cygroot = find_cygwin_root (&issystem);
+  int i;
+  for (i=0; shells[i]; i++)
+    {
+      sh = backslash (concat (cygroot, shells[i], 0));
+      if (_access (sh, 0) == 0)
+       break;
+      free (sh);
+      sh = 0;
+    }
+
+  char old_path[_MAX_PATH];
+  GetEnvironmentVariable ("PATH", old_path, sizeof (old_path));
+#if 0
+  SetEnvironmentVariable ("PATH",
+                         backslash (concat (root_dir, "/bin;",
+                                            root_dir, "/usr/bin;",
+                                            old_path, 0)));
+
+  SetEnvironmentVariable ("CYGWINROOT", root_dir);
+#endif
+  SetCurrentDirectory (root_dir);
+
+  verinfo.dwOSVersionInfoSize = sizeof (verinfo);
+  GetVersionEx (&verinfo);
+
+  switch (verinfo.dwPlatformId)
+    {
+    case VER_PLATFORM_WIN32_NT:
+      cmd = "cmd.exe";
+      break;
+    case VER_PLATFORM_WIN32_WINDOWS:
+      cmd = "command.com";
+      break;
+    default:
+      cmd = "command.com";
+      break;
+    }
+
+  find (concat (root_dir, XEMACS_SETUP_DIR, "postinstall", 0), each);
+}
diff --git a/netinstall/regedit.cc b/netinstall/regedit.cc
new file mode 100644 (file)
index 0000000..0c69495
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * 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>
+ *
+ */
+
+/* Manipulate the registry for XEmacs. */
+
+#include "win32.h"
+
+#include <stdio.h>
+#if defined(CYGWIN) || defined(MINGW)
+#include <cygwin/version.h>
+#include <sys/mount.h>
+#endif
+
+#include "reginfo.h"
+#include "regedit.h"
+#include "msg.h"
+#include "resource.h"
+#include "dialog.h"
+
+static char *
+find_cygwin_mount (HKEY rkey, int *istext)
+{
+  char buf[1000];
+  char *retval = 0;
+  HKEY key;
+  DWORD retvallen = 0;
+  DWORD flags = 0;
+  DWORD type;
+
+#if defined(CYGWIN) || defined(MINGW)
+  sprintf (buf, "Software\\%s\\%s\\%s\\/",
+          CYGWIN_INFO_CYGNUS_REGISTRY_NAME,
+          CYGWIN_INFO_CYGWIN_REGISTRY_NAME,
+          CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME);
+
+  if (RegOpenKeyEx (rkey, buf, 0, KEY_READ, &key) != ERROR_SUCCESS)
+    return 0;
+
+  if (RegQueryValueEx (key, "native", 0, &type, 0, &retvallen)
+      == ERROR_SUCCESS)
+    {
+      retval = new char[retvallen+1];
+      if (RegQueryValueEx (key, "native", 0, &type, (BYTE *)retval, &retvallen)
+         != ERROR_SUCCESS)
+       {
+         delete retval;
+         retval = 0;
+       }
+    }
+
+  retvallen = sizeof (flags);
+  RegQueryValueEx (key, "flags", 0, &type, (BYTE *)&flags, &retvallen);
+
+  RegCloseKey (key);
+
+  if (retval)
+    *istext = (flags & MOUNT_BINARY) ? 0 : 1;
+  return retval;
+#else
+  return 0;
+#endif
+}
+
+static char *
+find_xemacs_root (HKEY rkey, int* isnative)
+{
+  char buf[1000];
+  char *retval = 0;
+  HKEY key;
+  DWORD retvallen = 0;
+  DWORD type;
+  DWORD itype;
+
+  sprintf (buf, "Software\\%s\\%s",
+          XEMACS_INFO_XEMACS_ORG_REGISTRY_NAME,
+          XEMACS_INFO_XEMACS_REGISTRY_NAME);
+
+  if (RegOpenKeyEx (rkey, buf, 0, KEY_READ, &key) != ERROR_SUCCESS)
+    return 0;
+
+  if (RegQueryValueEx (key, XEMACS_INFO_XEMACS_ROOT_KEY,
+                      0, &type, 0, &retvallen) == ERROR_SUCCESS)
+    {
+      retval = new char[retvallen+1];
+      if (RegQueryValueEx (key, XEMACS_INFO_XEMACS_ROOT_KEY,
+                          0, &type, (BYTE *)retval, &retvallen) 
+         != ERROR_SUCCESS)
+       {
+         delete retval;
+         retval = 0;
+       }
+    }
+
+  retvallen = sizeof (itype);
+  RegQueryValueEx (key, XEMACS_INFO_XEMACS_ROOT_TYPE, 
+                  0, &type, (BYTE *)&itype, &retvallen);
+
+  if (itype == 1)
+    *isnative = 1;
+  else
+    *isnative = 0;
+
+  RegCloseKey (key);
+
+  return retval;
+}
+
+char *
+find_root_location (int *issystem, int *isnative)
+{
+  char *rv;
+  if ((rv = find_xemacs_root (HKEY_CURRENT_USER, isnative)))
+    {
+      *issystem = 0;
+      return rv;
+    }
+  else if ((rv = find_xemacs_root (HKEY_LOCAL_MACHINE, isnative)))
+    {
+      *issystem = 1;
+      return rv;
+    }
+  return 0;
+}
+
+char *
+find_cygwin_root (int *issystem)
+{
+  char *rv;
+  int istext;
+  if ((rv = find_cygwin_mount (HKEY_CURRENT_USER, &istext)))
+    {
+      *issystem = 0;
+      return rv;
+    }
+  else if ((rv = find_cygwin_mount (HKEY_LOCAL_MACHINE, &istext)))
+    {
+      *issystem = 1;
+      return rv;
+    }
+  return 0;
+}
+
+void
+create_xemacs_root (char *path, int issystem, int isnative)
+{
+  char buf[1000];
+  HKEY key;
+  DWORD disposition;
+  DWORD itype = isnative ? 1 : 0;
+
+  remove_xemacs_root ();
+
+  sprintf (buf, "Software\\%s\\%s",
+          XEMACS_INFO_XEMACS_ORG_REGISTRY_NAME,
+          XEMACS_INFO_XEMACS_REGISTRY_NAME);
+
+  HKEY kr = issystem ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
+  if (RegCreateKeyEx (kr, buf, 0, "XEmacs", 0, KEY_ALL_ACCESS,
+                     0, &key, &disposition) != ERROR_SUCCESS)
+    fatal ("create_xemacs_root");
+
+  RegSetValueEx (key, XEMACS_INFO_XEMACS_ROOT_KEY, 
+                0, REG_SZ, (BYTE *)path, strlen (path)+1);
+  RegSetValueEx (key, XEMACS_INFO_XEMACS_ROOT_TYPE, 
+                0, REG_DWORD, (BYTE *)&itype, sizeof (itype));
+}
+
+void
+set_app_path (char *exe, char* path, int issystem)
+{
+  char buf[1000];
+  HKEY key;
+  DWORD disposition;
+
+  sprintf (buf, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\%s",
+          exe);
+
+  HKEY kr = issystem ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
+  RegDeleteKey (kr, buf);
+  
+  if (RegCreateKeyEx (kr, buf, 0, "XEmacs", 0, KEY_ALL_ACCESS,
+                     0, &key, &disposition) != ERROR_SUCCESS)
+    fatal ("set_app_path");
+
+  RegSetValueEx (key, "Path", 
+                0, REG_SZ, (BYTE *)path, strlen (path)+1);
+}
+
+static void
+remove1 (HKEY rkey)
+{
+  char buf[1000];
+
+  sprintf (buf, "Software\\%s\\%s",
+          XEMACS_INFO_XEMACS_ORG_REGISTRY_NAME,
+          XEMACS_INFO_XEMACS_REGISTRY_NAME);
+
+  RegDeleteKey (rkey, buf);
+}
+
+void
+remove_xemacs_root ()
+{
+  remove1 (HKEY_LOCAL_MACHINE);
+  remove1 (HKEY_CURRENT_USER);
+}
+
diff --git a/netinstall/regedit.h b/netinstall/regedit.h
new file mode 100644 (file)
index 0000000..4944c9e
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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>
+ *
+ */
+
+/* Finds the existing root point, or returns NULL. */
+
+char * find_root_location (int *issystem, int *isnative);
+char * find_cygwin_root (int *issystem);
+
+/* Similar to the mount and umount functions, but simplified */
+
+void   create_xemacs_root (char *posix, int issystem, int isnative);
+void   remove_xemacs_root ();
+void   set_app_path (char *exe, char* path, int issystem);
+
diff --git a/netinstall/reginfo.h b/netinstall/reginfo.h
new file mode 100644 (file)
index 0000000..36c0cd2
--- /dev/null
@@ -0,0 +1,56 @@
+/* reginfo.h -- XEmacs version numbers and accompanying documentation.
+
+Copyright (C) 2000 Andy Piper. */
+
+#define XEMACS_INFO_XEMACS_ORG_REGISTRY_NAME "GNU"
+#define XEMACS_INFO_XEMACS_REGISTRY_NAME "XEmacs"
+/* Keys */
+#define XEMACS_INFO_XEMACS_ROOT_KEY "emacs_dir"
+#define XEMACS_INFO_XEMACS_ROOT_TYPE "install_type"
+#define XEMACS_INFO_XEMACS_PACKAGE_KEY "EMACSPACKAGEPATH"
+#define XEMACS_INFO_XEMACS_VERSION_KEY "version"
+
+#define XEMACS_DEFAULT_ROOT "\\Program Files\\XEmacs"
+#define XEMACS_CYGWIN_DEFAULT_ROOT "\\usr\\local"
+
+#define XEMACS_SETUP_DIR \
+  ((char*)(install_type == IDC_INSTALL_NATIVE ? "\\setup\\" : "/lib/xemacs/setup/"))
+#define XEMACS_RESOURCE_DIR \
+  ((char*)(install_type == IDC_INSTALL_NATIVE ? "\\" : "/lib/xemacs/"))
+#define XEMACS_PACKAGE_DIR \
+  ((char*)(install_type == IDC_INSTALL_NATIVE ? "\\xemacs-packages\\" \
+                                   : "/lib/xemacs/xemacs-packages/"))
+#define XEMACS_NATIVE_ARCH_NAME "i586-pc-win32"
+#define XEMACS_CYGWIN_ARCH_NAME "i686-pc-cygwin32"
+
+/*
+ * Installation hierarchy is:
+ * C:\Program Files\XEmacs
+ *                     \xemacs-packages
+ *                             \etc
+ *                             \info
+ *                             \lib-src
+ *                             \lisp
+ *                             \man
+ *                             \pkginfo
+ *                     \site-packages
+ *                     \mule-packages
+ *                     \XEmacs-21.2
+ *                             \i586-pc-win32
+ *                             \etc
+ *                             \info
+ *                             \lisp
+ * Or:
+ * /usr/local/lib
+ *             /xemacs/xemacs-packages
+ *             /xemacs/site-packages
+ *             /xemacs/mule-packages
+ *             /xemacs-21.2
+ *                             /i686-pc-cygwin32
+ *                             /etc
+ *                             /info
+ *                             /lisp
+ * /usr/local/bin/i686-pc-cygwin32
+ */
+
diff --git a/netinstall/res.rc b/netinstall/res.rc
new file mode 100644 (file)
index 0000000..2d59534
--- /dev/null
@@ -0,0 +1,513 @@
+//Microsoft Developer Studio generated resource script.\r
+//\r
+#include "resource.h"\r
+\r
+#define APSTUDIO_READONLY_SYMBOLS\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Generated from the TEXTINCLUDE 2 resource.\r
+//\r
+#define APSTUDIO_HIDDEN_SYMBOLS\r
+#include "windows.h"\r
+#undef APSTUDIO_HIDDEN_SYMBOLS\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#undef APSTUDIO_READONLY_SYMBOLS\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// English (U.S.) resources\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r
+#ifdef _WIN32\r
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\r
+#pragma code_page(1252)\r
+#endif //_WIN32\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Dialog\r
+//\r
+\r
+IDD_SOURCE DIALOG DISCARDABLE  0, 0, 311, 201\r
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU\r
+CAPTION "XEmacs Setup"\r
+FONT 8, "MS Sans Serif"\r
+BEGIN\r
+    DEFPUSHBUTTON   "Next >",IDOK,199,176,45,15,WS_DISABLED\r
+    PUSHBUTTON      "Cancel",IDCANCEL,256,176,45,15\r
+    LTEXT           "",IDC_STATIC,10,10,87,151,SS_SUNKEN | NOT WS_GROUP\r
+    LTEXT           "",IDC_STATIC,10,169,291,1,SS_SUNKEN | NOT WS_GROUP\r
+    LTEXT           "Setup will use the following installation method.",\r
+                    IDC_STATIC,112,11,170,17\r
+    LTEXT           "To exit setup click Cancel at any time.",IDC_STATIC,112,\r
+                    32,166,17\r
+    CONTROL         "Download from the Internet",IDC_SOURCE_DOWNLOAD,"Button",\r
+                    BS_AUTORADIOBUTTON,127,102,152,10\r
+    CONTROL         "Install from the Internet",IDC_SOURCE_NETINST,"Button",\r
+                    BS_AUTORADIOBUTTON,127,121,87,10\r
+    CONTROL         "Install from Local Directory",IDC_SOURCE_CWD,"Button",\r
+                    BS_AUTORADIOBUTTON,127,140,104,10\r
+    GROUPBOX        "Installation method",IDC_STATIC,113,84,188,77\r
+    CONTROL         "GNU",IDC_STATIC,"Static",SS_BITMAP,19,36,69,62\r
+END\r
+\r
+IDD_LOCAL_DIR DIALOG DISCARDABLE  0, 0, 311, 201\r
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU\r
+CAPTION "Local package directory"\r
+FONT 8, "MS Sans Serif"\r
+BEGIN\r
+    DEFPUSHBUTTON   "Next >",IDOK,199,176,45,15,WS_DISABLED\r
+    PUSHBUTTON      "< Back",IDC_BACK,154,176,45,15\r
+    PUSHBUTTON      "Cancel",IDCANCEL,256,176,45,15\r
+    LTEXT           "",IDC_STATIC,10,10,87,151,SS_SUNKEN | NOT WS_GROUP\r
+    LTEXT           "",IDC_STATIC,10,169,291,1,SS_SUNKEN | NOT WS_GROUP\r
+    EDITTEXT        IDC_LOCAL_DIR,120,138,122,12,ES_AUTOHSCROLL\r
+    PUSHBUTTON      "Browse...",IDC_LOCAL_DIR_BROWSE,252,137,38,14\r
+    LTEXT           "Setup will use the following folder to install XEmacs and / or packages from.",\r
+                    IDC_STATIC,112,10,170,17\r
+    LTEXT           "To select a different folder, click Browse and select another folder.",\r
+                    IDC_STATIC,112,36,170,18\r
+    LTEXT           "To exit setup click Cancel at any time.",IDC_STATIC,112,\r
+                    63,166,17\r
+    GROUPBOX        "Local Package Directory",IDC_STATIC,112,126,186,31\r
+    CONTROL         "GNU",IDC_STATIC,"Static",SS_BITMAP,19,36,69,62\r
+END\r
+\r
+IDD_ROOT DIALOG DISCARDABLE  0, 0, 311, 201\r
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU\r
+CAPTION "XEmacs Setup"\r
+FONT 8, "MS Sans Serif"\r
+BEGIN\r
+    DEFPUSHBUTTON   "Next >",IDOK,199,176,45,15\r
+    PUSHBUTTON      "< Back",IDC_BACK,154,176,45,15\r
+    PUSHBUTTON      "Cancel",IDCANCEL,256,176,45,15\r
+    LTEXT           "",IDC_STATIC,10,10,87,151,SS_SUNKEN | NOT WS_GROUP\r
+    LTEXT           "",IDC_STATIC,10,169,291,1,SS_SUNKEN | NOT WS_GROUP\r
+    EDITTEXT        IDC_ROOT_DIR,120,138,122,12,ES_AUTOHSCROLL\r
+    PUSHBUTTON      "Browse...",IDC_ROOT_BROWSE,252,137,38,14\r
+    LTEXT           "Setup will use the following folder in which to install XEmacs and / or packages.",\r
+                    IDC_STATIC,112,10,170,17\r
+    LTEXT           "To select a different folder, click Browse and select another folder.",\r
+                    IDC_STATIC,112,35,170,18\r
+    LTEXT           "To exit setup click Cancel at any time.",IDC_STATIC,112,\r
+                    63,166,17\r
+    GROUPBOX        "Installation Root Directory",IDC_STATIC,112,126,186,31\r
+    CONTROL         "All",IDC_ROOT_SYSTEM,"Button",BS_AUTORADIOBUTTON | \r
+                    WS_GROUP,177,110,25,8\r
+    CONTROL         "Just Me",IDC_ROOT_USER,"Button",BS_AUTORADIOBUTTON,220,\r
+                    110,50,8\r
+    LTEXT           "Installation Type :",IDC_STATIC,112,95,60,8\r
+    LTEXT           "Install For :",IDC_STATIC,112,110,43,8\r
+    CONTROL         "Native",IDC_INSTALL_NATIVE,"Button",BS_AUTORADIOBUTTON,\r
+                    177,93,37,10\r
+    CONTROL         "Cygwin",IDC_INSTALL_CYGWIN,"Button",BS_AUTORADIOBUTTON,\r
+                    220,93,39,10\r
+    CONTROL         "GNU",IDC_STATIC,"Static",SS_BITMAP,19,36,69,62\r
+END\r
+\r
+IDD_SITE DIALOG DISCARDABLE  0, 0, 311, 201\r
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU\r
+CAPTION "XEmacs Setup"\r
+FONT 8, "MS Sans Serif"\r
+BEGIN\r
+    DEFPUSHBUTTON   "Next >",IDOK,199,176,45,15\r
+    PUSHBUTTON      "< Back",IDC_BACK,154,176,45,15\r
+    PUSHBUTTON      "Cancel",IDCANCEL,256,176,45,15\r
+    LTEXT           "",IDC_STATIC,10,10,87,151,SS_SUNKEN | NOT WS_GROUP\r
+    LTEXT           "",IDC_STATIC,10,169,291,1,SS_SUNKEN | NOT WS_GROUP\r
+    LTEXT           "Select Download Site",IDC_STATIC,113,11,135,11\r
+    LISTBOX         IDC_URL_LIST,121,24,179,136,LBS_NOINTEGRALHEIGHT | \r
+                    WS_VSCROLL | WS_HSCROLL | WS_TABSTOP\r
+    CONTROL         "GNU",IDC_STATIC,"Static",SS_BITMAP,19,36,69,62\r
+END\r
+\r
+IDD_OTHER_URL DIALOG DISCARDABLE  0, 0, 311, 201\r
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU\r
+CAPTION "XEmacs Setup"\r
+FONT 8, "MS Sans Serif"\r
+BEGIN\r
+    DEFPUSHBUTTON   "Next >",IDOK,199,176,45,15\r
+    PUSHBUTTON      "< Back",IDC_BACK,154,176,45,15\r
+    PUSHBUTTON      "Cancel",IDCANCEL,256,176,45,15\r
+    LTEXT           "",IDC_STATIC,10,10,87,151,SS_SUNKEN | NOT WS_GROUP\r
+    LTEXT           "",IDC_STATIC,10,169,291,1,SS_SUNKEN | NOT WS_GROUP\r
+    EDITTEXT        IDC_OTHER_URL,120,138,170,12,ES_AUTOHSCROLL\r
+    LTEXT           "Setup will use the following URL to install XEmacs and / or packages from.",\r
+                    IDC_STATIC,112,10,170,17\r
+    LTEXT           "To select a different URL, edit the text.",IDC_STATIC,\r
+                    112,36,170,18\r
+    LTEXT           "To exit setup click Cancel at any time.",IDC_STATIC,112,\r
+                    58,166,17\r
+    GROUPBOX        "Select URL to download from",IDC_STATIC,112,126,186,31\r
+    CONTROL         "GNU",IDC_STATIC,"Static",SS_BITMAP,19,36,69,62\r
+END\r
+\r
+IDD_NET DIALOGEX 0, 0, 311, 201\r
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU\r
+CAPTION "XEmacs Setup"\r
+FONT 8, "MS Sans Serif"\r
+BEGIN\r
+    DEFPUSHBUTTON   "Next >",IDOK,199,176,45,15\r
+    PUSHBUTTON      "< Back",IDC_BACK,154,176,45,15\r
+    PUSHBUTTON      "Cancel",IDCANCEL,256,176,45,15\r
+    LTEXT           "",IDC_STATIC,10,10,87,151,SS_SUNKEN | NOT WS_GROUP\r
+    LTEXT           "",IDC_STATIC,10,169,291,1,SS_SUNKEN | NOT WS_GROUP\r
+    LTEXT           "Setup will use the following connection method.",\r
+                    IDC_STATIC,112,11,170,17\r
+    LTEXT           "To exit setup click Cancel at any time.",IDC_STATIC,112,\r
+                    32,166,17\r
+    CONTROL         "Use IE5 Settings",IDC_NET_IE5,"Button",\r
+                    BS_AUTORADIOBUTTON,128,93,69,10\r
+    CONTROL         "Direct Connection",IDC_NET_DIRECT,"Button",\r
+                    BS_AUTORADIOBUTTON,128,109,73,10\r
+    CONTROL         "Use HTTP/FTP Proxy:",IDC_NET_PROXY,"Button",\r
+                    BS_AUTORADIOBUTTON,128,124,88,10\r
+    EDITTEXT        IDC_PROXY_HOST,128,141,80,12,ES_AUTOHSCROLL | \r
+                    WS_DISABLED\r
+    LTEXT           "Proxy",IDC_STATIC,10,55,50,15,SS_CENTERIMAGE,\r
+                    WS_EX_RIGHT\r
+    LTEXT           "Port",IDC_STATIC,229,139,20,15,SS_CENTERIMAGE,\r
+                    WS_EX_RIGHT\r
+    EDITTEXT        IDC_PROXY_PORT,257,141,30,12,ES_AUTOHSCROLL | \r
+                    WS_DISABLED\r
+    GROUPBOX        "Installation method",IDC_STATIC,113,78,188,83\r
+    CONTROL         "GNU",IDC_STATIC,"Static",SS_BITMAP,19,36,69,62\r
+END\r
+\r
+IDD_DLSTATUS DIALOG DISCARDABLE  0, 0, 215, 95\r
+STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_POPUP | WS_VISIBLE | \r
+    WS_CAPTION | WS_SYSMENU\r
+CAPTION "XEmacs Setup"\r
+FONT 8, "MS Sans Serif"\r
+BEGIN\r
+    PUSHBUTTON      "Cancel",IDCANCEL,165,75,45,15\r
+    LTEXT           "Downloading...",IDC_STATIC,55,15,135,8\r
+    LTEXT           "(URL)",IDC_DLS_URL,55,30,150,8\r
+    LTEXT           "(RATE)",IDC_DLS_RATE,55,45,155,8\r
+    CONTROL         "Progress1",IDC_DLS_PROGRESS,"msctls_progress32",\r
+                    PBS_SMOOTH | WS_BORDER,55,60,155,10\r
+    ICON            IDI_XEMACS,IDC_STATIC,5,5,20,20\r
+END\r
+\r
+IDD_INSTATUS DIALOG DISCARDABLE  0, 0, 215, 95\r
+STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_POPUP | WS_VISIBLE | \r
+    WS_CAPTION | WS_SYSMENU\r
+CAPTION "XEmacs Setup"\r
+FONT 8, "MS Sans Serif"\r
+BEGIN\r
+    PUSHBUTTON      "Cancel",IDCANCEL,165,75,45,15\r
+    LTEXT           "Installing...",IDC_INS_ACTION,55,5,135,8\r
+    LTEXT           "(PKG)",IDC_INS_PKG,55,15,150,8\r
+    LTEXT           "(FILE)",IDC_INS_FILE,55,25,155,8\r
+    CONTROL         "Progress1",IDC_INS_DISKFULL,"msctls_progress32",\r
+                    PBS_SMOOTH | WS_BORDER,55,60,155,10\r
+    ICON            IDI_XEMACS,IDC_STATIC,5,5,20,20\r
+    CONTROL         "Progress1",IDC_INS_IPROGRESS,"msctls_progress32",\r
+                    PBS_SMOOTH | WS_BORDER,55,50,155,10\r
+    CONTROL         "Progress1",IDC_INS_PPROGRESS,"msctls_progress32",\r
+                    PBS_SMOOTH | WS_BORDER,55,40,155,10\r
+    RTEXT           "Package",IDC_STATIC,5,40,45,8\r
+    RTEXT           "Total",IDC_STATIC,10,50,40,8\r
+    RTEXT           "Disk",IDC_STATIC,5,60,45,8\r
+END\r
+\r
+IDD_PROXY_AUTH DIALOG DISCARDABLE  0, 0, 215, 95\r
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU\r
+CAPTION "XEmacs Setup"\r
+FONT 8, "MS Sans Serif"\r
+BEGIN\r
+    ICON            IDI_XEMACS,IDC_STATIC,5,5,20,20\r
+    EDITTEXT        IDC_NET_USER,65,28,145,12,ES_AUTOHSCROLL\r
+    LTEXT           "Proxy User ID",IDC_STATIC,5,28,55,15,SS_CENTERIMAGE,\r
+                    WS_EX_RIGHT\r
+    EDITTEXT        IDC_NET_PASSWD,65,43,145,12,ES_PASSWORD | ES_AUTOHSCROLL\r
+    LTEXT           "Password",IDC_STATIC,10,43,50,15,SS_CENTERIMAGE,\r
+                    WS_EX_RIGHT\r
+    LTEXT           "Proxy Authorization Required",IDC_STATIC,65,10,145,10\r
+    DEFPUSHBUTTON   "OK",IDOK,100,75,45,15,WS_DISABLED\r
+    PUSHBUTTON      "Cancel",IDCANCEL,165,75,45,15\r
+END\r
+\r
+IDD_NET_AUTH DIALOG DISCARDABLE  0, 0, 215, 95\r
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU\r
+CAPTION "XEmacs Setup"\r
+FONT 8, "MS Sans Serif"\r
+BEGIN\r
+    ICON            IDI_XEMACS,IDC_STATIC,5,5,20,20\r
+    EDITTEXT        IDC_NET_USER,65,28,145,12,ES_AUTOHSCROLL\r
+    LTEXT           "User ID",IDC_STATIC,5,28,55,15,SS_CENTERIMAGE,\r
+                    WS_EX_RIGHT\r
+    EDITTEXT        IDC_NET_PASSWD,65,43,145,12,ES_PASSWORD | ES_AUTOHSCROLL\r
+    LTEXT           "Password",IDC_STATIC,10,43,50,15,SS_CENTERIMAGE,\r
+                    WS_EX_RIGHT\r
+    LTEXT           "Server Authorization Required",IDC_STATIC,65,10,145,10\r
+    DEFPUSHBUTTON   "OK",IDOK,100,75,45,15,WS_DISABLED\r
+    PUSHBUTTON      "Cancel",IDCANCEL,165,75,45,15\r
+END\r
+\r
+IDD_SPLASH DIALOGEX 0, 0, 311, 201\r
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU\r
+CAPTION "XEmacs Setup"\r
+FONT 8, "MS Sans Serif"\r
+BEGIN\r
+    DEFPUSHBUTTON   "Next >",IDOK,199,176,45,15\r
+    PUSHBUTTON      "Cancel",IDCANCEL,256,176,45,15\r
+    ICON            IDI_XEMACS,IDC_STATIC,107,10,20,20\r
+    LTEXT           "Welcome to the XEmacs Net Release Setup Program. This will install XEmacs and/or associated packages on your computer.",\r
+                    IDC_STATIC,133,10,158,29\r
+    LTEXT           "Version (unknown)",IDC_VERSION,112,117,120,10\r
+    LTEXT           "Copyright (C) 2000 Red Hat Inc",IDC_STATIC,111,132,135,\r
+                    8\r
+    LTEXT           "http://www.xemacs.org/",IDC_STATIC,111,147,150,10\r
+    LTEXT           "It is strongly recommended that you exit all Windows programs before running this utility.",\r
+                    IDC_STATIC,110,43,191,19\r
+    LTEXT           "",IDC_STATIC,10,169,291,1,SS_SUNKEN | NOT WS_GROUP\r
+    LTEXT           "",IDC_STATIC,10,10,87,151,SS_SUNKEN | NOT WS_GROUP\r
+    CONTROL         "GNU",IDC_STATIC,"Static",SS_BITMAP,19,36,69,62\r
+END\r
+\r
+IDD_CHOOSE DIALOG DISCARDABLE  0, 0, 311, 239\r
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU\r
+CAPTION "XEmacs Setup"\r
+FONT 8, "MS Sans Serif"\r
+BEGIN\r
+    DEFPUSHBUTTON   "Next >",IDOK,199,214,45,15\r
+    PUSHBUTTON      "< Back",IDC_BACK,154,214,45,15\r
+    PUSHBUTTON      "Cancel",IDCANCEL,256,214,45,15\r
+    LTEXT           "",IDC_STATIC,10,201,291,1,SS_SUNKEN | NOT WS_GROUP\r
+    LTEXT           "Select packages to install",IDC_STATIC,55,5,85,8\r
+    ICON            IDI_XEMACS,IDC_STATIC,5,5,21,20\r
+    LTEXT           "",IDC_LISTVIEW_POS,55,15,230,155,SS_SUNKEN | NOT \r
+                    WS_VISIBLE | NOT WS_GROUP\r
+    CONTROL         "SPIN",IDC_STATIC,"Static",SS_BITMAP,55,170,15,13\r
+    LTEXT           "= click to choose action, (p) = previous version, (x) = experimental",\r
+                    IDC_STATIC,65,170,220,8\r
+    PUSHBUTTON      "Full/Part",IDC_CHOOSE_FULLPART,250,5,35,10\r
+    PUSHBUTTON      "Exp",IDC_CHOOSE_EXP,215,5,25,10\r
+    PUSHBUTTON      "Curr",IDC_CHOOSE_CURR,190,5,25,10\r
+    PUSHBUTTON      "Prev",IDC_CHOOSE_PREV,165,5,25,10\r
+END\r
+\r
+IDD_DESKTOP DIALOG DISCARDABLE  0, 0, 311, 201\r
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU\r
+CAPTION "XEmacs Setup"\r
+FONT 8, "MS Sans Serif"\r
+BEGIN\r
+    DEFPUSHBUTTON   "Finish",IDOK,199,176,45,15\r
+    PUSHBUTTON      "< Back",IDC_BACK,154,176,45,15\r
+    PUSHBUTTON      "Cancel",IDCANCEL,256,176,45,15\r
+    LTEXT           "",IDC_STATIC,10,10,87,151,SS_SUNKEN | NOT WS_GROUP\r
+    LTEXT           "",IDC_STATIC,10,169,291,1,SS_SUNKEN | NOT WS_GROUP\r
+    LTEXT           "Setup has now finished. To create desktop shortcuts, please select from the following options.",\r
+                    IDC_STATIC,112,11,170,17\r
+    LTEXT           "To complete setup click Finish.",IDC_STATIC,112,32,166,\r
+                    17\r
+    CONTROL         "Create Desktop Icon",IDC_ROOT_DESKTOP,"Button",\r
+                    BS_AUTOCHECKBOX,113,76,100,8\r
+    CONTROL         "Add to Start Menu",IDC_ROOT_MENU,"Button",\r
+                    BS_AUTOCHECKBOX,113,97,100,8\r
+    CONTROL         "GNU",IDC_STATIC,"Static",SS_BITMAP,19,36,69,62\r
+END\r
+\r
+\r
+#ifdef APSTUDIO_INVOKED\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// TEXTINCLUDE\r
+//\r
+\r
+1 TEXTINCLUDE DISCARDABLE \r
+BEGIN\r
+    "resource.h\0"\r
+END\r
+\r
+2 TEXTINCLUDE DISCARDABLE \r
+BEGIN\r
+    "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"\r
+    "#include ""windows.h""\r\n"\r
+    "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"\r
+    "\0"\r
+END\r
+\r
+3 TEXTINCLUDE DISCARDABLE \r
+BEGIN\r
+    "\r\n"\r
+    "\0"\r
+END\r
+\r
+#endif    // APSTUDIO_INVOKED\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Icon\r
+//\r
+\r
+// Icon with lowest ID value placed first to ensure application icon\r
+// remains consistent on all systems.\r
+IDI_XEMACS              ICON    DISCARDABLE     "xemacs.ico"\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// FILE\r
+//\r
+\r
+XEMACS.ICON             FILE    DISCARDABLE     "xemacs.ico"\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// DESIGNINFO\r
+//\r
+\r
+#ifdef APSTUDIO_INVOKED\r
+GUIDELINES DESIGNINFO DISCARDABLE \r
+BEGIN\r
+    IDD_SOURCE, DIALOG\r
+    BEGIN\r
+        VERTGUIDE, 113\r
+        VERTGUIDE, 127\r
+    END\r
+\r
+    IDD_LOCAL_DIR, DIALOG\r
+    BEGIN\r
+        VERTGUIDE, 112\r
+        HORZGUIDE, 10\r
+    END\r
+\r
+    IDD_ROOT, DIALOG\r
+    BEGIN\r
+        VERTGUIDE, 112\r
+        HORZGUIDE, 103\r
+        HORZGUIDE, 118\r
+    END\r
+\r
+    IDD_SITE, DIALOG\r
+    BEGIN\r
+        HORZGUIDE, 11\r
+        HORZGUIDE, 161\r
+    END\r
+\r
+    IDD_NET, DIALOG\r
+    BEGIN\r
+        VERTGUIDE, 128\r
+        BOTTOMMARGIN, 191\r
+        HORZGUIDE, 153\r
+    END\r
+\r
+    IDD_PROXY_AUTH, DIALOG\r
+    BEGIN\r
+        BOTTOMMARGIN, 49\r
+    END\r
+\r
+    IDD_NET_AUTH, DIALOG\r
+    BEGIN\r
+        BOTTOMMARGIN, 49\r
+    END\r
+\r
+    IDD_SPLASH, DIALOG\r
+    BEGIN\r
+        LEFTMARGIN, 10\r
+        RIGHTMARGIN, 301\r
+        TOPMARGIN, 10\r
+        BOTTOMMARGIN, 191\r
+    END\r
+\r
+    IDD_CHOOSE, DIALOG\r
+    BEGIN\r
+        BOTTOMMARGIN, 229\r
+        HORZGUIDE, 214\r
+    END\r
+\r
+    IDD_DESKTOP, DIALOG\r
+    BEGIN\r
+        VERTGUIDE, 113\r
+    END\r
+END\r
+#endif    // APSTUDIO_INVOKED\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Bitmap\r
+//\r
+\r
+SPIN                    BITMAP  DISCARDABLE     "choose-spin.bmp"\r
+IDB_SPIN                BITMAP  DISCARDABLE     "choose-spin.bmp"\r
+IDB_RTARROW             BITMAP  DISCARDABLE     "choose-rtarrow.bmp"\r
+IDB_CHECK_YES           BITMAP  DISCARDABLE     "check-yes.bmp"\r
+IDB_CHECK_NO            BITMAP  DISCARDABLE     "check-no.bmp"\r
+IDB_CHECK_NA            BITMAP  DISCARDABLE     "check-na.bmp"\r
+GNU                 BITMAP  DISCARDABLE     "gnu.bmp"\r
+IDB_GNU                 BITMAP  DISCARDABLE     "gnu.bmp"\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// String Table\r
+//\r
+\r
+STRINGTABLE DISCARDABLE \r
+BEGIN\r
+    IDS_ROOT_SLASH          "Warning: we recommend you do NOT use the root of your hard drive as the XEmacs root.  Proceed anyway?"\r
+    IDS_ROOT_SPACE          "You should not choose a root path that include spaces in directory names.  Proceed anyway?"\r
+    IDS_MIRROR_LST          "http://ftp.xemacs.org/pub/xemacs/mirrors.lst"\r
+    IDS_DIALOG_FAILED       "Unable to create Dialog Box"\r
+    IDS_CYGWIN_FUNC_MISSING "Error: unable to find function `%s' in %s"\r
+    IDS_DOWNLOAD_SHORT      "Download error: %s too short (%d, wanted %d)"\r
+    IDS_ERR_OPEN_WRITE      "Can't open %s for writing: %s"\r
+    IDS_SETUPINI_MISSING    "Unable to get setup.ini from %s"\r
+    IDS_OLD_SETUPINI        "This setup.ini is older than the one you used last time you installed cygwin.  Proceed anyway?"\r
+    IDS_ERR_RENAME          "Can't rename %s to %s: %s"\r
+    IDS_NOTHING_INSTALLED   "Nothing needed to be installed"\r
+    IDS_INSTALL_COMPLETE    "Installation Complete"\r
+END\r
+\r
+STRINGTABLE DISCARDABLE \r
+BEGIN\r
+    IDS_ERR_OPEN_READ       "Can't open %s for reading: %s"\r
+    IDS_ROOT_ABSOLUTE       "The install directory must be absolute, with both a drive letter and leading slash, like C:\\Cygwin"\r
+    IDS_DOWNLOAD_COMPLETE   "Download Complete"\r
+    IDS_CVSID               "\n%%% $Id: res.rc,v 1.1.2.3 2000/12/27 09:35:11 andyp Exp $\n"\r
+    IDS_NOLOGFILE           "Cannot open log file %s for writing"\r
+    IDS_UNINSTALL_COMPLETE  "Uninstalls complete."\r
+    IDS_WININET             "Unable to find or load the Internet Explorer 5 DLLs"\r
+    IDS_ERR_CHDIR           "Could not change dir to %s"\r
+    IDS_OLD_SETUP_VERSION   "This setup is version %s, but setup.ini claims version %s is available.\nYou might want to upgrade to get the latest features and bug fixes."\r
+    IDS_DOWNLOAD_FAILED     "Unable to download %s"\r
+    IDS_DOWNLOAD_INCOMPLETE "Download Incomplete.  Try again?"\r
+    IDS_INSTALL_INCOMPLETE  "Installation incomplete.  Check /setup.log.full for details"\r
+    IDS_ROOT_NOCYGWIN       "You should not install the Cygwin version without Cygwin installed.  Proceed anyway?"\r
+END\r
+\r
+#endif    // English (U.S.) resources\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// English (U.K.) resources\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)\r
+#ifdef _WIN32\r
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK\r
+#pragma code_page(1252)\r
+#endif //_WIN32\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Bitmap\r
+//\r
+\r
+#endif    // English (U.K.) resources\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+\r
+\r
+#ifndef APSTUDIO_INVOKED\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Generated from the TEXTINCLUDE 3 resource.\r
+//\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#endif    // not APSTUDIO_INVOKED\r
+\r
diff --git a/netinstall/resource.h b/netinstall/resource.h
new file mode 100644 (file)
index 0000000..20cf78b
--- /dev/null
@@ -0,0 +1,113 @@
+//{{NO_DEPENDENCIES}}\r
+// Microsoft Developer Studio generated include file.\r
+// Used by res.rc\r
+//\r
+#define IDS_ROOT_SLASH                  1\r
+#define IDS_ROOT_SPACE                  2\r
+#define IDS_CWD_NONEMPTY                3\r
+#define IDS_MIRROR_LST                  6\r
+#define IDS_DIALOG_FAILED               7\r
+#define IDS_CYGWIN_FUNC_MISSING         8\r
+#define IDS_DOWNLOAD_SHORT              9\r
+#define IDS_ERR_OPEN_WRITE              10\r
+#define IDS_SETUPINI_MISSING            11\r
+#define IDS_OLD_SETUPINI                12\r
+#define IDS_ERR_RENAME                  13\r
+#define IDS_NOTHING_INSTALLED           14\r
+#define IDS_INSTALL_COMPLETE            15\r
+#define IDS_ERR_OPEN_READ               16\r
+#define IDS_ROOT_ABSOLUTE               17\r
+#define IDS_DOWNLOAD_COMPLETE           18\r
+#define IDS_CVSID                       19\r
+#define IDS_NOLOGFILE                   20\r
+#define IDS_UNINSTALL_COMPLETE          21\r
+#define IDS_WININET                     22\r
+#define IDS_ERR_CHDIR                   23\r
+#define IDS_OLD_SETUP_VERSION           24\r
+#define IDS_DOWNLOAD_FAILED             25\r
+#define IDS_DOWNLOAD_INCOMPLETE         26\r
+#define IDS_INSTALL_INCOMPLETE          27\r
+#define IDS_ROOT_NOCYGWIN               28\r
+#define IDD_ROOT                        101\r
+#define IDD_SOURCE                      102\r
+#define IDD_OTHER_URL                   103\r
+#define IDD_SITE                        104\r
+#define IDD_NET                         105\r
+#define IDD_DLSTATUS                    106\r
+#define IDD_S_LOAD_INI                  107\r
+#define IDD_S_FROM_CWD                  108\r
+#define IDD_CHOOSE                      109\r
+#define IDD_S_DOWNLOAD                  110\r
+#define IDD_S_INSTALL                   111\r
+#define IDD_INSTATUS                    112\r
+#define IDD_DESKTOP                     113\r
+#define IDD_PROXY_AUTH                  114\r
+#define IDD_S_POSTINSTALL               115\r
+#define IDD_NET_AUTH                    116\r
+#define IDD_SPLASH                      117\r
+#define IDB_SPIN                        118\r
+#define IDB_RTARROW                     119\r
+#define IDI_SPIN                        120\r
+#define IDI_XEMACS                      121\r
+#define IDD_LOCAL_DIR                   122\r
+#define IDB_CHECK_YES                   123\r
+#define IDB_CHECK_NO                    124\r
+#define IDB_CHECK_NA                    125\r
+#define IDB_GNU                         126\r
+#define IDC_SOURCE_DOWNLOAD             1000\r
+#define IDC_SOURCE_NETINST              1001\r
+#define IDC_SOURCE_CWD                  1002\r
+#define IDC_ROOT_DIR                    1003\r
+#define IDC_ROOT_BROWSE                 1004\r
+#define IDC_ROOT_TEXT                   1005\r
+#define IDC_ROOT_BINARY                 1006\r
+#define IDC_URL_LIST                    1007\r
+#define IDC_SITE_NEXT                   1008\r
+#define IDC_BACK                        1009\r
+#define IDC_OTHER_URL                   1010\r
+#define IDC_NET_IE5                     1011\r
+#define IDC_NET_DIRECT                  1012\r
+#define IDC_NET_PROXY                   1013\r
+#define IDC_PROXY_HOST                  1014\r
+#define IDC_PROXY_PORT                  1015\r
+#define IDC_PROXY_USER                  1016\r
+#define IDC_DLS_PROGRESS                1019\r
+#define IDC_DLS_URL                     1020\r
+#define IDC_DLS_RATE                    1021\r
+#define IDC_INS_PKG                     1022\r
+#define IDC_INS_FILE                    1023\r
+#define IDC_INS_DISKFULL                1024\r
+#define IDC_INS_IPROGRESS               1025\r
+#define IDC_INS_PPROGRESS               1026\r
+#define IDC_ROOT_SYSTEM                 1028\r
+#define IDC_ROOT_USER                   1029\r
+#define IDC_NET_USER                    1030\r
+#define IDC_NET_PASSWD                  1031\r
+#define IDC_VERSION                     1033\r
+#define IDC_LISTVIEW_POS                1034\r
+#define IDC_CHOOSE_FULLPART             1035\r
+#define IDC_CHOOSE_EXP                  1036\r
+#define IDC_CHOOSE_CURR                 1037\r
+#define IDC_CHOOSE_PREV                 1038\r
+#define IDC_CHOOSE_LIST                 1039\r
+#define IDC_INS_ACTION                  1040\r
+#define IDC_ROOT_DESKTOP                1041\r
+#define IDC_ROOT_MENU                   1042\r
+#define IDC_LOCAL_DIR_BROWSE            1043\r
+#define IDC_LOCAL_DIR                   1044\r
+#define IDC_INSTALL_NATIVE              1045\r
+#define IDC_INSTALL_CYGWIN              1046\r
+#define IDC_STATIC                      -1\r
+\r
+// Next default values for new objects\r
+// \r
+#ifdef APSTUDIO_INVOKED\r
+#ifndef APSTUDIO_READONLY_SYMBOLS\r
+#define _APS_NO_MFC                     1\r
+#define _APS_3D_CONTROLS                     1\r
+#define _APS_NEXT_RESOURCE_VALUE        127\r
+#define _APS_NEXT_COMMAND_VALUE         40003\r
+#define _APS_NEXT_CONTROL_VALUE         1050\r
+#define _APS_NEXT_SYMED_VALUE           101\r
+#endif\r
+#endif\r
diff --git a/netinstall/root.cc b/netinstall/root.cc
new file mode 100644 (file)
index 0000000..2378151
--- /dev/null
@@ -0,0 +1,334 @@
+/*
+ * 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 ask the user where they want the
+   root of the installation to be, and to ask whether the user prefers
+   text or binary mounts. */
+
+#include "win32.h"
+#include <shlobj.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "dialog.h"
+#include "resource.h"
+#include "state.h"
+#include "msg.h"
+#include "regedit.h"
+#include "reginfo.h"
+#include "concat.h"
+#include "log.h"
+
+static int rb[] = { IDC_INSTALL_CYGWIN, IDC_INSTALL_NATIVE, 0 };
+static int su[] = { IDC_ROOT_SYSTEM, IDC_ROOT_USER, 0 };
+
+static void
+check_if_enable_next (HWND h)
+{
+  EnableWindow (GetDlgItem (h, IDOK), install_type && root_dir && root_scope);
+}
+
+static void
+load_dialog (HWND h)
+{
+  rbset (h, rb, install_type);
+  rbset (h, su, root_scope);
+  eset (h, IDC_ROOT_DIR, root_dir);
+  check_if_enable_next (h);
+}
+
+static void
+save_dialog (HWND h)
+{
+  install_type = rbget (h, rb);
+  root_scope = rbget (h, su);
+  char* new_root_dir = eget (h, IDC_ROOT_DIR, root_dir);
+
+  if (!root_dir || strcmp (new_root_dir, root_dir) != 0)
+    root_dir_default = 0;
+
+  root_dir = new_root_dir;
+}
+
+/*
+ * is_admin () determines whether or not the current user is a member of the
+ * Administrators group.  On Windows 9X, the current user is considered an
+ * Administrator by definition.
+ */
+
+static int
+is_admin ()
+{
+  // Windows 9X users are considered Administrators by definition
+  OSVERSIONINFO verinfo;
+  verinfo.dwOSVersionInfoSize = sizeof (verinfo);
+  GetVersionEx (&verinfo);
+  if (verinfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
+    return 1;
+
+  // Get the process token for the current process
+  HANDLE token;
+  BOOL status = OpenProcessToken (GetCurrentProcess(), TOKEN_QUERY, &token);
+  if (!status)
+    return 0;
+
+  // Get the group token information
+  UCHAR token_info[1024];
+  PTOKEN_GROUPS groups = (PTOKEN_GROUPS) token_info;
+  DWORD token_info_len = sizeof (token_info);
+  status = GetTokenInformation (token, TokenGroups, token_info, token_info_len, &token_info_len);
+  CloseHandle(token);
+  if (!status)
+    return 0;
+
+  // Create the Administrators group SID
+  PSID admin_sid;
+  SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_AUTHORITY;
+  status = AllocateAndInitializeSid (&authority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &admin_sid);
+  if (!status)
+    return 0;
+
+  // Check to see if the user is a member of the Administrators group
+  status = 0;
+  for (UINT i=0; i<groups->GroupCount; i++) {
+    if (EqualSid(groups->Groups[i].Sid, admin_sid)) {
+      status = 1;
+      break;
+    }
+  }
+
+  // Destroy the Administrators group SID
+  FreeSid (admin_sid);
+
+  // Return whether or not the user is a member of the Administrators group
+  return status;
+}
+
+static void
+change_default_root (int id)
+{
+  int issystem;
+  char* cygroot = find_cygwin_root (&issystem);
+  if (id == IDC_INSTALL_CYGWIN && cygroot)
+    {
+      root_dir = concat (cygroot, XEMACS_CYGWIN_DEFAULT_ROOT, 0);
+      install_type = IDC_INSTALL_CYGWIN;
+    }
+  else if (id == IDC_INSTALL_NATIVE)
+    {
+      char windir[_MAX_PATH];
+      GetWindowsDirectory (windir, sizeof (windir));
+      windir[2] = 0;
+      root_dir = concat (windir, XEMACS_DEFAULT_ROOT, 0);
+      install_type = IDC_INSTALL_NATIVE;
+    }
+}
+
+static void
+read_mount_table ()
+{
+  int isnative, issystem;
+  root_dir = find_root_location (&issystem, &isnative);
+  if (root_dir)
+    {
+      if (isnative)
+       install_type = IDC_INSTALL_NATIVE;
+      else
+       install_type = IDC_INSTALL_CYGWIN;
+
+      if (issystem)
+       root_scope = IDC_ROOT_SYSTEM;
+      else
+       root_scope = IDC_ROOT_USER;
+      root_dir_default = 0;
+    }
+  else
+    {
+      change_default_root (IDC_INSTALL_NATIVE);
+      root_scope = (is_admin()) ? IDC_ROOT_SYSTEM : IDC_ROOT_USER;
+      root_dir_default = 1;
+    }
+}
+
+static int CALLBACK
+browse_cb (HWND h, UINT m, LPARAM lp, LPARAM data)
+{
+  switch (m)
+    {
+    case BFFM_INITIALIZED:
+      if (root_dir)
+       SendMessage (h, BFFM_SETSELECTION, TRUE, (LPARAM)root_dir);
+      break;
+    }
+  return 0;
+}
+
+static void
+browse (HWND h)
+{
+  BROWSEINFO bi;
+  CHAR name[MAX_PATH];
+  LPITEMIDLIST pidl;
+  memset (&bi, 0, sizeof (bi));
+  bi.hwndOwner = h;
+  bi.pszDisplayName = name;
+  bi.lpszTitle = "Select an installation root directory";
+  bi.ulFlags = BIF_RETURNONLYFSDIRS;
+  bi.lpfn = browse_cb;
+  pidl = SHBrowseForFolder (&bi);
+  if (pidl)
+    {
+      if (SHGetPathFromIDList (pidl, name))
+       eset (h, IDC_ROOT_DIR, name);
+    }
+}
+
+#define isslash(c) ((c) == '\\' || (c) == '/')
+
+static int
+directory_is_absolute ()
+{
+  if (isalpha (root_dir[0])
+      && root_dir[1] == ':'
+      && (root_dir[2] == '\\' || root_dir[2] == '/'))
+    return 1;
+  return 0;
+}
+
+static int
+directory_is_rootdir ()
+{
+  char *c;
+  for (c = root_dir; *c; c++)
+    if (isslash (c[0]) && c[1] && !isslash (c[1]))
+      return 0;
+  return 1;
+}
+
+static int
+cygwin_without_cygwin ()
+{
+  int issystem;
+  if (install_type == IDC_INSTALL_CYGWIN
+      && !find_cygwin_root (&issystem))
+    return 1;
+  return 0;
+}
+
+static BOOL
+dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
+{
+  switch (id)
+    {
+
+    case IDC_ROOT_DIR:
+    case IDC_ROOT_SYSTEM:
+    case IDC_ROOT_USER:
+      save_dialog (h);
+      check_if_enable_next (h);
+      break;
+
+    case IDC_INSTALL_NATIVE:
+    case IDC_INSTALL_CYGWIN:
+      if (root_dir_default)
+       {
+         change_default_root (id);
+         eset (h, IDC_ROOT_DIR, root_dir);
+       }
+      save_dialog (h);
+      check_if_enable_next (h);
+      break;
+
+    case IDC_ROOT_BROWSE:
+      browse (h);
+      break;
+
+    case IDOK:
+      save_dialog (h);
+
+      if (! directory_is_absolute ())
+       {
+         note (IDS_ROOT_ABSOLUTE);
+         break;
+       }
+
+      if (directory_is_rootdir ())
+       if (IDNO == yesno (IDS_ROOT_SLASH))
+         break;
+
+      if (cygwin_without_cygwin ())
+       if (IDNO == yesno (IDS_ROOT_NOCYGWIN))
+         break;
+
+      create_xemacs_root (root_dir,
+                         root_scope == IDC_ROOT_SYSTEM ? 1 : 0,
+                         install_type == IDC_INSTALL_NATIVE ? 1 : 0);
+
+      switch (source)
+       {
+       case IDC_SOURCE_NETINST:
+         NEXT (IDD_NET);
+         break;
+       case IDC_SOURCE_CWD:
+         NEXT (IDD_S_FROM_CWD);
+         break;
+       default:
+         msg ("source is default? %d\n", source);
+         NEXT (0);
+       }
+      break;
+
+    case IDC_BACK:
+      save_dialog (h);
+      NEXT (IDD_LOCAL_DIR);
+      break;
+
+    case IDCANCEL:
+      NEXT (0);
+      break;
+    }
+  return FALSE;
+}
+
+static BOOL CALLBACK
+dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  switch (message)
+    {
+    case WM_INITDIALOG:
+      load_dialog (h);
+      return FALSE;
+    case WM_COMMAND:
+      return HANDLE_WM_COMMAND (h, wParam, lParam, dialog_cmd);
+    }
+  return FALSE;
+}
+
+void
+do_root (HINSTANCE h)
+{
+  int rv = 0;
+  read_mount_table ();
+
+  rv = DialogBox (h, MAKEINTRESOURCE (IDD_ROOT), 0, dialog_proc);
+  if (rv == -1)
+    fatal (IDS_DIALOG_FAILED);
+
+  log (0, "root: %s %s %s", root_dir,
+       (install_type == IDC_INSTALL_NATIVE) ? "native" : "cygwin",
+       (root_scope == IDC_ROOT_USER) ? "user" : "system");
+}
+
diff --git a/netinstall/setup.mak b/netinstall/setup.mak
new file mode 100644 (file)
index 0000000..333e00a
--- /dev/null
@@ -0,0 +1,247 @@
+#   Makefile for Microsoft NMAKE
+#   Copyright (C) 1995 Board of Trustees, University of Illinois.
+#   Copyright (C) 1995, 1996, 2000 Ben Wing.
+#   Copyright (C) 1995 Sun Microsystems, Inc.
+#   Copyright (C) 1998 Free Software Foundation, Inc.
+#
+# This file is part of XEmacs.
+#
+# XEmacs 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, or (at your option) any
+# later version.
+#
+# XEmacs is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with XEmacs; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+#
+# Synched up with: Not in FSF.
+#
+
+TARGETOS=BOTH
+APPVER=4.0
+!include "c:\Program Files\Microsoft Platform SDK\Include\win32.mak"
+
+default: all
+
+# APA: Since there seems to be no way to determine the directory where
+# xemacs.mak is located (from within nmake) we just insist on the user
+# to invoke nmake in the directory where xemacs.mak is.
+!if !exist("$(MAKEDIR)\setup.mak")
+!error Please run nmake from the directory of this makefile (xemacs\netinstall).
+!endif
+
+XEMACS=$(MAKEDIR)\..
+
+# Define a variable for the 'del' command to use
+DEL=-del
+
+# Configuration from nt subdirectory if needed
+
+!include "$(XEMACS)\nt\config.inc"
+
+OUTDIR = obj
+
+#
+# Compiler command echo control. Define VERBOSECC=1 to get verbose compilation.
+#
+!if !defined(VERBOSECC)
+VERBOSECC=0
+!endif
+!if $(VERBOSECC)
+cc=$(cc)
+!else
+cc=@$(cc)
+!endif
+
+!if $(DEBUG_XEMACS)
+cdebug=-Od -Gr -Zi -Zp8
+!else
+cdebug=-Oxsb2 -Oy- -G5rFs -Zi -Zp8
+!endif
+
+defines = -DWIN32_NATIVE -I$(ZLIBDIR) $(ZLIB_FLAGS)
+
+#
+# Object files
+#
+OBJS =         \
+       $(OUTDIR)\choose.obj \
+       $(OUTDIR)\concat.obj \
+       $(OUTDIR)\desktop.obj \
+       $(OUTDIR)\dialog.obj \
+       $(OUTDIR)\diskfull.obj \
+       $(OUTDIR)\download.obj \
+       $(OUTDIR)\find.obj \
+       $(OUTDIR)\fromcwd.obj \
+       $(OUTDIR)\geturl.obj \
+       $(OUTDIR)\hash.obj \
+       $(OUTDIR)\ini.obj \
+       $(OUTDIR)\inilex.obj \
+       $(OUTDIR)\iniparse.obj \
+       $(OUTDIR)\install.obj \
+       $(OUTDIR)\localdir.obj \
+       $(OUTDIR)\log.obj \
+       $(OUTDIR)\main.obj \
+       $(OUTDIR)\mkdir.obj \
+       $(OUTDIR)\mklink2.obj \
+       $(OUTDIR)\regedit.obj \
+       $(OUTDIR)\msg.obj \
+       $(OUTDIR)\net.obj \
+       $(OUTDIR)\netio.obj \
+       $(OUTDIR)\nio-ie5.obj \
+       $(OUTDIR)\nio-file.obj \
+       $(OUTDIR)\nio-ftp.obj \
+       $(OUTDIR)\nio-http.obj \
+       $(OUTDIR)\other.obj \
+       $(OUTDIR)\postinstall.obj \
+#      $(OUTDIR)\res.obj \
+       $(OUTDIR)\root.obj \
+       $(OUTDIR)\simpsock.obj \
+       $(OUTDIR)\site.obj \
+       $(OUTDIR)\source.obj \
+       $(OUTDIR)\splash.obj \
+       $(OUTDIR)\state.obj \
+       $(OUTDIR)\tar.obj \
+       $(OUTDIR)\version.obj
+
+#
+# Libraries
+#
+LIBS = libcmt.lib $(olelibsmt) \
+       kernel32.lib shell32.lib \
+       wsock32.lib netapi32.lib \
+       wininet.lib $(zlib)
+
+# Rules
+
+.SUFFIXES:
+.SUFFIXES:     .c .cc .obj .texi .info
+
+# nmake rule
+.cc{$(OUTDIR)}.obj:
+       $(cc) /TP $(cflags) $(cdebug) $(cvarsmt) $(defines) -Fo$@ $<
+.c{$(OUTDIR)}.obj:
+       $(cc) $(cflags) $(cdebug) $(cvarsmt) $(defines) -Fo$@ $<
+
+#
+# Main target
+#
+all: setup.exe
+
+#
+# Link target. setargv.obj is provided in the compiler library directory.
+#
+setup.exe: $(OUTDIR) $(OBJS) res.res
+       $(link) /OUT:$@ $(ldebug) $(guilflags) $(OBJS) res.res $(LIBS)
+
+iniparse.c iniparse.h : iniparse.y
+       bison -d -o iniparse.c $(srcdir)/iniparse.y
+
+$(OUTDIR)\inilex.obj: iniparse.h
+
+inilex.c : inilex.l iniparse.h
+       flex -t $(srcdir)/inilex.l | sed "/^extern int isatty YY/d" > inilex.c
+
+version.c : $(srcdir)/ChangeLog version.pl
+       perl version.pl < ChangeLog > version.c
+
+res.res: res.rc
+       $(rc) $(rcvars) $(rcflags) /fo$@ $**
+
+$(OUTDIR):
+       -@mkdir $(OUTDIR)
+
+install:: all
+
+clean::
+       $(DEL) $(OUTDIR)\*.obj *.pdb *.aps res.res lex.yy.c
+
+distclean:: clean
+       $(DEL) *~ setup.exe
+
+# DO NOT DELETE
+
+$(OUTDIR)/autoload.obj: autoload.c win32.h 
+$(OUTDIR)/inilex.obj: inilex.c win32.h  ini.h iniparse.h \
+       
+$(OUTDIR)/iniparse.obj: iniparse.c ini.h iniparse.h port.h
+$(OUTDIR)/inilex.obj: inilex.c win32.h  ini.h iniparse.h
+$(OUTDIR)/mklink2.obj: mklink2.c win32.h 
+$(OUTDIR)/choose.obj: choose.cc win32.h  dialog.h resource.h \
+       state.h ini.h concat.h msg.h log.h find.h reginfo.h
+$(OUTDIR)/concat.obj: concat.cc win32.h
+$(OUTDIR)/desktop.obj: desktop.cc win32.h  \
+       resource.h ini.h msg.h state.h \
+       concat.h mkdir.h dialog.h version.h reginfo.h regedit.h port.h
+$(OUTDIR)/dialog.obj: dialog.cc win32.h  dialog.h msg.h log.h \
+       win32.h
+$(OUTDIR)/diskfull.obj: diskfull.cc  diskfull.h
+$(OUTDIR)/download.obj: download.cc win32.h  resource.h msg.h \
+       ini.h dialog.h concat.h geturl.h state.h mkdir.h log.h
+$(OUTDIR)/find.obj: find.cc win32.h  port.h
+$(OUTDIR)/fromcwd.obj: fromcwd.cc win32.h  \
+       ini.h resource.h concat.h \
+       state.h dialog.h msg.h find.h version.h port.h
+$(OUTDIR)/geturl.obj: geturl.cc win32.h  dialog.h geturl.h \
+       resource.h netio.h msg.h log.h
+$(OUTDIR)/hash.obj: hash.cc win32.h hash.h
+$(OUTDIR)/ini.obj: ini.cc win32.h  ini.h resource.h concat.h \
+       state.h geturl.h dialog.h msg.h mkdir.h log.h reginfo.h version.h
+$(OUTDIR)/install.obj: install.cc win32.h  \
+       $(ZLIBDIR)/zlib.h $(ZLIBDIR)/zconf.h \
+       resource.h ini.h dialog.h concat.h geturl.h mkdir.h state.h tar.h \
+       diskfull.h msg.h regedit.h reginfo.h log.h hash.h port.h
+$(OUTDIR)/localdir.obj: localdir.cc win32.h  dialog.h resource.h \
+       state.h msg.h concat.h log.h
+$(OUTDIR)/log.obj: log.cc win32.h  resource.h msg.h log.h dialog.h \
+       state.h concat.h mkdir.h
+$(OUTDIR)/main.obj: main.cc win32.h  resource.h dialog.h state.h \
+       msg.h netio.h find.h log.h port.h
+$(OUTDIR)/mkdir.obj: mkdir.cc win32.h  mkdir.h
+$(OUTDIR)/msg.obj: msg.cc win32.h  dialog.h log.h
+$(OUTDIR)/net.obj: net.cc win32.h  dialog.h resource.h state.h \
+       msg.h log.h
+$(OUTDIR)/netio.obj: netio.cc win32.h  resource.h state.h msg.h \
+       netio.h nio-file.h nio-ie5.h nio-http.h nio-ftp.h dialog.h log.h port.h \
+       win32.h
+$(OUTDIR)/nio-file.obj: nio-file.cc  netio.h nio-file.h resource.h \
+       msg.h
+$(OUTDIR)/nio-ftp.obj: nio-ftp.cc win32.h  resource.h state.h \
+       simpsock.h log.h netio.h nio-ftp.h
+$(OUTDIR)/nio-http.obj: nio-http.cc win32.h  resource.h state.h \
+       simpsock.h msg.h netio.h nio-http.h
+$(OUTDIR)/nio-ie5.obj: nio-ie5.cc win32.h  resource.h state.h \
+       dialog.h msg.h netio.h nio-ie5.h
+$(OUTDIR)/other.obj: other.cc win32.h  dialog.h resource.h state.h \
+       msg.h log.h
+$(OUTDIR)/postinstall.obj: postinstall.cc win32.h  \
+       state.h dialog.h find.h \
+       concat.h regedit.h reginfo.h resource.h port.h
+$(OUTDIR)/regedit.obj: regedit.cc win32.h  reginfo.h regedit.h \
+       msg.h resource.h dialog.h
+$(OUTDIR)/root.obj: root.cc win32.h  dialog.h resource.h state.h \
+       msg.h regedit.h reginfo.h concat.h log.h
+$(OUTDIR)/simpsock.obj: simpsock.cc win32.h  simpsock.h msg.h \
+       win32.h
+$(OUTDIR)/site.obj: site.cc  dialog.h resource.h state.h geturl.h \
+       msg.h concat.h regedit.h reginfo.h log.h port.h
+$(OUTDIR)/source.obj: source.cc win32.h  dialog.h resource.h \
+       state.h msg.h log.h
+$(OUTDIR)/splash.obj: splash.cc win32.h  dialog.h resource.h msg.h \
+       version.h
+$(OUTDIR)/state.obj: state.cc state.h
+$(OUTDIR)/tar.obj: tar.cc win32.h  \
+       $(ZLIBDIR)/zlib.h $(ZLIBDIR)/zconf.h \
+       tar.h mkdir.h log.h port.h
+
+#\f
+# Local Variables:
+# mode: makefile
+# End:
diff --git a/netinstall/simpsock.cc b/netinstall/simpsock.cc
new file mode 100644 (file)
index 0000000..db1f806
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * 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>
+ *
+ */
+
+/* Simplified socket access functions */
+
+#include "win32.h"
+#include <winsock.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+#include "simpsock.h"
+#include "msg.h"
+
+#define SSBUFSZ 1024
+
+SimpleSocket::SimpleSocket (char *hostname, int port)
+{
+  static int initted = 0;
+  if (!initted)
+    {
+      initted = 1;
+      WSADATA d;
+      WSAStartup (MAKEWORD (1,1), &d);
+    }
+
+  s = INVALID_SOCKET;
+  buf = (char *) malloc (SSBUFSZ + 3);
+  putp = getp = 0;
+
+  int i1, i2, i3, i4;
+  unsigned char ip[4];
+
+  if (sscanf (hostname, "%d.%d.%d.%d", &i1, &i2, &i3, &i4) == 4)
+    {
+      ip[0] = i1;
+      ip[1] = i2;
+      ip[2] = i3;
+      ip[3] = i4;
+    }
+  else
+    {
+      struct hostent *he;
+      he = gethostbyname (hostname);
+      if (!he)
+       {
+         msg ("Can't resolve `%s'\n", hostname);
+         return;
+       }
+      memcpy (ip, he->h_addr_list[0], 4);
+    }
+
+  s = socket (AF_INET, SOCK_STREAM, 0);
+  if (s == INVALID_SOCKET)
+    {
+      msg ("Can't create socket, %d", WSAGetLastError ());
+      return;
+    }
+
+  struct sockaddr_in name;
+
+  memset (&name, 0, sizeof (name));
+  name.sin_family = AF_INET;
+  name.sin_port = htons (port);
+  memcpy (&name.sin_addr, ip, 4);
+
+  if (connect (s, (sockaddr *)&name, sizeof(name)))
+    {
+      msg ("Can't connect to %s:%d", hostname, port);
+      closesocket (s);
+      s = INVALID_SOCKET;
+      return;
+    }
+
+  return;
+}
+
+SimpleSocket::~SimpleSocket ()
+{
+  if (s != INVALID_SOCKET)
+    closesocket (s);
+  s = INVALID_SOCKET;
+  if (buf)
+    free (buf);
+  buf = 0;
+}
+
+int
+SimpleSocket::ok ()
+{
+  if (s == INVALID_SOCKET)
+    return 0;
+  return 1;
+}
+
+int
+SimpleSocket::printf (char *fmt, ...)
+{
+  char localbuf[SSBUFSZ];
+  va_list args;
+  va_start (args, fmt);
+  vsprintf (localbuf, fmt, args);
+  return send (s, localbuf, strlen (localbuf), 0);
+}
+
+int
+SimpleSocket::write (char *localbuf, int len)
+{
+  return send (s, localbuf, len, 0);
+}
+
+int
+SimpleSocket::fill ()
+{
+  if (putp == getp)
+    putp = getp = 0;
+
+  int n = SSBUFSZ - putp;
+  if (n == 0)
+    return 0;
+  int r = recv (s, buf + putp, n, 0);
+  if (r > 0)
+    {
+      putp += r;
+      return r;
+    }
+  return 0;
+}
+
+char *
+SimpleSocket::gets ()
+{
+  if (getp > 0 && putp > getp)
+    {
+      memmove (buf, buf+getp, putp-getp);
+      putp -= getp;
+      getp = 0;
+    }
+  if (putp == getp)
+    fill();
+
+  // getp is zero, always, here, and putp is the count
+  char *nl;
+  while ((nl = (char *)memchr (buf, '\n', putp)) == NULL && putp < SSBUFSZ)
+    if (fill () <= 0)
+      break;
+
+  if (nl)
+    {
+      getp = nl - buf + 1;
+      while ((*nl == '\n' || *nl == '\r') && nl >= buf)
+       *nl-- = 0;
+    }
+  else
+    {
+      getp = putp;
+      nl = buf + putp;
+      nl[1] = 0;
+    }
+
+  return buf;
+}
+
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+int
+SimpleSocket::read (char *ubuf, int ulen)
+{
+  int n, rv=0;
+  if (putp > getp)
+    {
+      n = MIN (ulen, putp-getp);
+      memmove (ubuf, buf+getp, n);
+      getp += n;
+      ubuf += n;
+      ulen -= n;
+      rv += n;
+    }
+  while (ulen > 0)
+    {
+      n = recv (s, ubuf, ulen, 0);
+      if (n <= 0)
+       return rv;
+      ubuf += n;
+      ulen -= n;
+      rv += n;
+    }
+  return rv;
+}
diff --git a/netinstall/simpsock.h b/netinstall/simpsock.h
new file mode 100644 (file)
index 0000000..cde49dd
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * 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>
+ *
+ */
+
+/* Simplified socket access functions */
+
+class SimpleSocket {
+
+  SOCKET s;
+  char *buf;
+  int putp, getp;
+  int fill ();
+
+ public:
+  SimpleSocket (char *hostname, int port);
+  ~SimpleSocket ();
+
+  int ok ();
+
+  int printf (char *fmt, ...);
+  int write (char *buf, int len);
+
+  char *gets ();
+  int  read (char *buf, int len);
+};
diff --git a/netinstall/site.cc b/netinstall/site.cc
new file mode 100644 (file)
index 0000000..f7eacf1
--- /dev/null
@@ -0,0 +1,329 @@
+/*
+ * 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 get the list of mirror sites and ask
+   the user which mirror site they want to download from. */
+
+#include "win32.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dialog.h"
+#include "resource.h"
+#include "state.h"
+#include "geturl.h"
+#include "msg.h"
+#include "concat.h"
+#include "regedit.h"
+#include "reginfo.h"
+#include "log.h"
+
+#include "port.h"
+
+#define NO_IDX (-1)
+#define OTHER_IDX (-2)
+
+typedef struct {
+  char *url;
+  char *displayed_url;
+  char *sort_key;
+} site_list_type;
+
+static site_list_type *site_list = 0;
+static int list_idx = NO_IDX;
+static int mirror_idx = NO_IDX;
+
+static void
+check_if_enable_next (HWND h)
+{
+  EnableWindow (GetDlgItem (h, IDOK), (mirror_idx != NO_IDX) ? 1 : 0);
+}
+
+static void
+load_dialog (HWND h)
+{
+  HWND listbox = GetDlgItem (h, IDC_URL_LIST);
+  SendMessage (listbox, LB_SETCURSEL, list_idx, 0);
+  check_if_enable_next (h);
+}
+
+static void
+save_dialog (HWND h)
+{
+  HWND listbox = GetDlgItem (h, IDC_URL_LIST);
+  list_idx = SendMessage (listbox, LB_GETCURSEL, 0, 0);
+  if (list_idx == LB_ERR)
+    {
+      mirror_site = 0;
+      mirror_idx = NO_IDX;
+      list_idx = NO_IDX;
+    }
+  else
+    {
+      mirror_idx = SendMessage (listbox, LB_GETITEMDATA, list_idx, 0);
+      if (mirror_idx == OTHER_IDX)
+       mirror_site = 0;
+      else
+       mirror_site = site_list[mirror_idx].url;
+    }
+}
+
+static void
+get_root_dir ()
+{
+  int issystem, isnative;
+  if (root_dir)
+    return;
+  root_dir = find_root_location (&issystem, &isnative);
+}
+
+void
+save_site_url ()
+{
+  if (! MIRROR_SITE)
+    return;
+
+  get_root_dir ();
+  if (! root_dir)
+    return;
+  
+  FILE *f = fopen (concat (root_dir, XEMACS_SETUP_DIR, "last-mirror", 0), "wb");
+  if (!f)
+    return;
+  fprintf (f, "%s\n", MIRROR_SITE);
+  fclose (f);
+}
+
+static BOOL
+dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
+{
+  switch (id)
+    {
+
+    case IDC_URL_LIST:
+      save_dialog (h);
+      check_if_enable_next (h);
+      break;
+
+    case IDOK:
+      save_dialog (h);
+      if (mirror_idx == OTHER_IDX)
+       NEXT (IDD_OTHER_URL);
+      else
+       {
+         other_url = 0;
+         save_site_url ();
+         NEXT (IDD_S_LOAD_INI);
+       }
+      break;
+
+    case IDC_BACK:
+      save_dialog (h);
+      NEXT (IDD_NET);
+      break;
+
+    case IDCANCEL:
+      NEXT (0);
+      break;
+    }
+  return FALSE;
+}
+
+static BOOL CALLBACK
+dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  int i, j;
+  HWND listbox;
+  switch (message)
+    {
+    case WM_INITDIALOG:
+      listbox = GetDlgItem (h, IDC_URL_LIST);
+      for (i=0; site_list[i].url; i++)
+       {
+         j = SendMessage (listbox, LB_ADDSTRING, 0, (LPARAM)site_list[i].displayed_url);
+         SendMessage (listbox, LB_SETITEMDATA, j, i);
+       }
+      j = SendMessage (listbox, LB_ADDSTRING, 0, (LPARAM)"Other URL");
+      SendMessage (listbox, LB_SETITEMDATA, j, OTHER_IDX);
+      load_dialog (h);
+      return FALSE;
+    case WM_COMMAND:
+      return HANDLE_WM_COMMAND (h, wParam, lParam, dialog_cmd);
+    }
+  return FALSE;
+}
+
+static int CDECL
+site_sort (const void *va, const void *vb)
+{
+  site_list_type *a = (site_list_type *)va;
+  site_list_type *b = (site_list_type *)vb;
+  return strcmp (a->sort_key, b->sort_key);
+}
+
+static int
+get_site_list (HINSTANCE h)
+{
+  char mirror_url[1000];
+  if (LoadString (h, IDS_MIRROR_LST, mirror_url, sizeof (mirror_url)) <= 0)
+    return 1;
+  char *mirrors = get_url_to_string (mirror_url);
+  dismiss_url_status_dialog ();
+  if (!mirrors)
+    return 1;
+
+  char *bol, *eol, *nl;
+
+  
+  /* null plus account for possibly missing NL plus account for "Other
+    URL" from previous run. */
+  int nmirrors = 3;
+
+  for (bol=mirrors; *bol; bol++)
+    if (*bol == '\n')
+      nmirrors ++;
+
+  site_list = (site_list_type *) malloc (nmirrors * sizeof (site_list_type));
+  nmirrors = 0;
+
+  nl = mirrors;
+  while (*nl)
+    {
+      bol = nl;
+      for (eol = bol; *eol && *eol != '\n'; eol++) ;
+      if (*eol)
+       nl = eol+1;
+      else
+       nl = eol;
+      while (eol > bol && eol[-1] == '\r')
+       eol--;
+      *eol = 0;
+      if (bol[0] != '#' && bol[0] > ' ')
+       {
+         char *semi = strchr (bol, ';');
+         if (semi)
+           *semi = 0;
+         site_list[nmirrors].url = _strdup (bol);
+         site_list[nmirrors].displayed_url = _strdup (bol);
+         char *dot = strchr (site_list[nmirrors].displayed_url, '.');
+         if (dot)
+           {
+             dot = strchr (dot, '/');
+             if (dot)
+               *dot = 0;
+           }
+         site_list[nmirrors].sort_key = (char *) malloc (2*strlen (bol) + 3);
+
+         dot = site_list[nmirrors].displayed_url;
+         dot += strlen (dot);
+         char *dp = site_list[nmirrors].sort_key;
+         while (dot != site_list[nmirrors].displayed_url)
+           {
+             if (*dot == '.' || *dot == '/')
+               {
+                 char *sp;
+                 if (dot[3] == 0)
+                   *dp++ = '~'; /* sort .com/.edu/.org together */
+                 for (sp=dot+1; *sp && *sp != '.' && *sp != '/';)
+                   *dp++ = *sp++;
+                 *dp++ = ' ';
+               }
+             dot--;
+           }
+         *dp++ = ' ';
+         strcpy (dp, site_list[nmirrors].displayed_url);
+
+         nmirrors++;
+       }
+    }
+  site_list[nmirrors].url = 0;
+
+  qsort (site_list, nmirrors, sizeof (site_list_type), site_sort);
+
+  return 0;
+}
+
+/* List of machines that should not be used by default when saved
+   in "last-mirror". */
+#define NOSAVE1 "ftp://ftp.xemacs.org/"
+#define NOSAVE1_LEN (sizeof ("ftp://ftp.xemacs.org/") - 1)
+
+static void
+get_initial_list_idx ()
+{
+  get_root_dir ();
+  if (! root_dir)
+    return;
+
+  FILE *f = fopen (concat (root_dir, XEMACS_SETUP_DIR, "last-mirror", 0), "rt");
+  if (!f)
+    return;
+
+  char site[1000];
+  site[0]='\0';
+  char * fg_ret = fgets (site, 1000, f);
+  fclose (f);
+  if (! fg_ret)
+    return;
+
+  char *eos = site + strlen (site) - 1;
+  while (eos >= site && (*eos == '\n' || *eos == '\r'))
+    *eos-- = '\0';
+
+  if (eos < site)
+    return;
+
+  int i;
+  for (i = 0; site_list[i].url; i++)
+    if (strcmp (site_list[i].url, site) == 0)
+      break;
+
+  if (! site_list[i].url)
+    {
+      /* Don't default to certain machines ever since they suffer
+        from bandwidth limitations. */
+      if (strnicmp (site, NOSAVE1, NOSAVE1_LEN) == 0)
+       return;
+      site_list[i].displayed_url =
+      site_list[i].url = _strdup (site);
+      site_list[i+1].url = 0;
+    }
+
+  mirror_idx = list_idx = i;
+}
+
+void
+do_site (HINSTANCE h)
+{
+  int rv = 0;
+
+  if (site_list == 0)
+    if (get_site_list (h))
+      {
+       NEXT (IDD_NET);
+       return;
+      }
+
+  get_initial_list_idx ();
+
+  rv = DialogBox (h, MAKEINTRESOURCE (IDD_SITE), 0, dialog_proc);
+  if (rv == -1)
+    fatal (IDS_DIALOG_FAILED);
+
+  if (mirror_idx != OTHER_IDX)
+    log (0, "site: %s", mirror_site);
+}
+
diff --git a/netinstall/source.cc b/netinstall/source.cc
new file mode 100644 (file)
index 0000000..a1aa889
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * 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 manage the dialog box that lets the
+   user choose the source of the install - from the net, from the
+   current directory, or to just download files. */
+
+#include "win32.h"
+#include <stdio.h>
+#include "dialog.h"
+#include "resource.h"
+#include "state.h"
+#include "msg.h"
+#include "log.h"
+
+static int rb[] = { IDC_SOURCE_DOWNLOAD, IDC_SOURCE_NETINST, IDC_SOURCE_CWD, 0 };
+
+static void
+check_if_enable_next (HWND h)
+{
+  EnableWindow (GetDlgItem (h, IDOK), source ? 1 : 0);
+}
+
+static void
+load_dialog (HWND h)
+{
+  rbset (h, rb, source);
+  check_if_enable_next (h);
+}
+
+static void
+save_dialog (HWND h)
+{
+  source = rbget (h, rb);
+}
+
+static BOOL
+dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
+{
+  switch (id)
+    {
+
+    case IDC_SOURCE_DOWNLOAD:
+    case IDC_SOURCE_NETINST:
+    case IDC_SOURCE_CWD:
+      save_dialog (h);
+      check_if_enable_next (h);
+      break;
+
+    case IDOK:
+      save_dialog (h);
+      NEXT (IDD_LOCAL_DIR);
+      break;
+
+    case IDC_BACK:
+      save_dialog (h);
+      NEXT (0);
+      break;
+
+    case IDCANCEL:
+      NEXT (0);
+      break;
+    }
+  return FALSE;
+}
+
+static BOOL CALLBACK
+dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  switch (message)
+    {
+    case WM_INITDIALOG:
+      load_dialog (h);
+      return FALSE;
+    case WM_COMMAND:
+      return HANDLE_WM_COMMAND (h, wParam, lParam, dialog_cmd);
+    }
+  return FALSE;
+}
+
+void
+do_source (HINSTANCE h)
+{
+  int rv = 0;
+  rv = DialogBox (h, MAKEINTRESOURCE (IDD_SOURCE), 0, dialog_proc);
+  if (rv == -1)
+    fatal (IDS_DIALOG_FAILED);
+
+  log (0, "source: %s",
+       (source == IDC_SOURCE_DOWNLOAD) ? "download" :
+       (source == IDC_SOURCE_NETINST) ? "network install" : "from cwd");
+}
+
diff --git a/netinstall/splash.cc b/netinstall/splash.cc
new file mode 100644 (file)
index 0000000..9c866c7
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * 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 display the program name, version,
+   copyright notice, and project URL. */
+
+#include "win32.h"
+#include <stdio.h>
+#include "dialog.h"
+#include "resource.h"
+#include "msg.h"
+#include "version.h"
+
+static void
+load_dialog (HWND h)
+{
+  char buffer[100];
+  HWND v = GetDlgItem (h, IDC_VERSION);
+  sprintf (buffer, "Setup.exe version %s",
+          version[0] ? version : "[unknown]");
+  SetWindowText (v, buffer);
+}
+
+static BOOL
+dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
+{
+  switch (id)
+    {
+
+    case IDOK:
+      NEXT (IDD_SOURCE);
+      break;
+
+    case IDCANCEL:
+      NEXT (0);
+      break;
+    }
+  return FALSE;
+}
+
+static BOOL CALLBACK
+dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  switch (message)
+    {
+    case WM_INITDIALOG:
+      load_dialog (h);
+      return FALSE;
+    case WM_COMMAND:
+      return HANDLE_WM_COMMAND (h, wParam, lParam, dialog_cmd);
+    }
+  return FALSE;
+}
+
+void
+do_splash (HINSTANCE h)
+{
+  int rv = 0;
+  HANDLE gnu = LoadImage (h, MAKEINTRESOURCE (IDB_GNU), IMAGE_BITMAP, 0, 0, 0);
+  rv = DialogBox (h, MAKEINTRESOURCE (IDD_SPLASH), 0, dialog_proc);
+  if (rv == -1)
+    fatal (IDS_DIALOG_FAILED);
+}
+
diff --git a/netinstall/state.cc b/netinstall/state.cc
new file mode 100644 (file)
index 0000000..23502c2
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * 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>
+ *
+ */
+
+/* All we do here is instantiate the extern'd variables from state.h */
+
+#define extern
+#include "state.h"
diff --git a/netinstall/state.h b/netinstall/state.h
new file mode 100644 (file)
index 0000000..6f11d78
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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 contain all the global variables
+   that define the "state" of the install, that is, all the
+   information that the user has provided so far.  These are set by
+   the various dialogs and used by the various actions. */
+
+extern int     source;
+
+extern char *  local_dir;
+
+extern char *  root_dir;
+extern int     root_dir_default;
+extern int     install_type;
+extern int     root_scope;
+extern int   root_menu;
+extern int   root_desktop;
+
+extern int     net_method;
+extern char *  net_proxy_host;
+extern int     net_proxy_port;
+
+extern char *  net_user;
+extern char *  net_passwd;
+extern char *  net_proxy_user;
+extern char *  net_proxy_passwd;
+
+extern char *  mirror_site;
+extern char *  other_url;
+
+extern int     trust_level;
+
+#define MIRROR_SITE (mirror_site ? mirror_site : other_url)
diff --git a/netinstall/tar.cc b/netinstall/tar.cc
new file mode 100644 (file)
index 0000000..8be129e
--- /dev/null
@@ -0,0 +1,511 @@
+/*
+ * 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>
+ *
+ */
+
+/* Built-in tar functionality.  See tar.h for usage. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "win32.h"
+#include <zlib.h>
+#include "tar.h"
+#include "mkdir.h"
+#include "log.h"
+
+#include "port.h"
+
+#if defined(CYGWIN) || defined(MINGW)
+#define FACTOR (0x19db1ded53ea710LL)
+#define NSPERSEC 10000000LL
+#else
+__int64 FACTOR=0x19db1ded53ea710L;
+__int64 NSPERSEC=10000000L;
+#endif
+#define SYMLINK_COOKIE "!<symlink>"
+
+typedef struct {
+  char name[100];               /*   0 */
+  char mode[8];                 /* 100 */
+  char uid[8];                  /* 108 */
+  char gid[8];                  /* 116 */
+  char size[12];                /* 124 */
+  char mtime[12];               /* 136 */
+  char chksum[8];               /* 148 */
+  char typeflag;                /* 156 */
+  char linkname[100];           /* 157 */
+  char magic[6];                /* 257 */
+  char version[2];              /* 263 */
+  char uname[32];               /* 265 */
+  char gname[32];               /* 297 */
+  char devmajor[8];             /* 329 */
+  char devminor[8];             /* 337 */
+  char prefix[155];             /* 345 */
+  char junk[12];               /* 500 */
+} tar_header_type;
+
+typedef struct tar_map_result_type_s {
+  struct tar_map_result_type_s *next;
+  char *stored_name;
+  char *mapped_name;
+} tar_map_result_type;
+
+static tar_map_result_type *tar_map_result = 0;
+
+static int err;
+
+static char file_name[_MAX_PATH+512];
+static char have_longname = 0;
+static int  file_length;
+
+static tar_header_type tar_header;
+static char buf[512];
+
+static int _tar_file_size = 0;
+int _tar_verbose = 0;
+FILE * _tar_vfile = 0;
+#define vp if (_tar_verbose) fprintf
+#define vp2 if (_tar_verbose>1) fprintf
+
+static gzFile g = 0;
+
+static char *
+xstrdup (char *c)
+{
+  char *r = (char *) malloc (strlen (c) + 1);
+  if (!r)
+    exit_setup (1);
+  strcpy (r, c);
+  return r;
+}
+
+int
+tar_open (char *pathname)
+{
+  struct stat s;
+  if (_tar_vfile == 0)
+    _tar_vfile = stderr;
+
+  vp2 (_tar_vfile, "tar: open `%s'\n", pathname);
+  if (stat (pathname, &s) < 0)
+    return 1;
+  _tar_file_size = s.st_size;
+
+  g = gzopen (pathname, "rb");
+  if (sizeof (tar_header) != 512)
+    {
+      /* drastic, but important */
+      fprintf (stderr, "compilation error: tar header struct not 512"
+              " bytes (it's %d)\n", sizeof (tar_header));
+      exit_setup (1);
+    }
+  err = 0;
+  return g ? 0 : 1;
+}
+
+int
+tar_ftell ()
+{
+  return gztell (g);
+}
+
+static void
+skip_file ()
+{
+  while (file_length > 0)
+    {
+      gzread (g, buf, 512);
+      file_length -= 512;
+    }
+}
+
+char *
+tar_next_file ()
+{
+  int r, n;
+  char *c;
+  r = gzread (g, &tar_header, 512);
+
+  /* See if we're at end of file */
+  if (r != 512)
+    return 0;
+
+  /* See if the header is all zeros (i.e. last block) */
+  n = 0;
+  for (r = 512/sizeof (int); r; r--)
+    n |= ((int *)&tar_header)[r-1];
+  if (n == 0)
+    return 0;
+
+  if (!have_longname && tar_header.typeflag != 'L')
+    {
+      memcpy (file_name, tar_header.name, 100);
+      file_name[100] = 0;
+    }
+
+  sscanf (tar_header.size, "%o", &file_length);
+
+  vp2 (_tar_vfile, "%c %9d %s\n", tar_header.typeflag, file_length, file_name);
+
+  switch (tar_header.typeflag)
+    {
+    case 'L': /* GNU tar long name extension */
+      if (file_length > _MAX_PATH)
+       {
+         skip_file ();
+         fprintf (stderr, "error: long file name exceeds %d characters\n",
+                  _MAX_PATH);
+         err ++;
+         gzread (g, &tar_header, 512);
+         sscanf (tar_header.size, "%o", &file_length);
+         skip_file ();
+         return tar_next_file ();
+       }
+      c = file_name;
+      while (file_length > 0)
+       {
+         int need = file_length > 512 ? 512 : file_length;
+         if (gzread (g, buf, 512) < 512)
+           return 0;
+         memcpy (c, buf, need);
+         c += need;
+         file_length -= need;
+       }
+      *c = 0;
+      have_longname = 1;
+      return tar_next_file ();
+
+    case '3': /* char */
+    case '4': /* block */
+    case '6': /* fifo */
+      fprintf (stderr, "warning: not extracting special file %s\n",
+              file_name);
+      err ++;
+      return tar_next_file ();
+
+    case '0': /* regular file */
+    case 0: /* regular file also */
+    case '2': /* symbolic link */
+    case '5': /* directory */
+    case '7': /* contiguous file */
+      return file_name;
+
+    case '1': /* hard link, we just copy */
+      return file_name;
+
+    default:
+      fprintf (stderr, "error: unknown (or unsupported) file type `%c'\n",
+              tar_header.typeflag);
+      err ++;
+      skip_file ();
+      return tar_next_file ();
+    }
+}
+
+static void
+fix_time_stamp (char *path)
+{
+  int mtime;
+#if defined(CYGWIN) || defined(MINGW)
+  long long ftimev;
+#else
+  __int64 ftimev;
+#endif
+  FILETIME ftime;
+  HANDLE h;
+
+  sscanf (tar_header.mtime, "%o", &mtime);
+  ftimev = mtime * NSPERSEC + FACTOR;
+  ftime.dwHighDateTime = ftimev >> 32;
+  ftime.dwLowDateTime = ftimev;
+  h = CreateFileA (path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
+                  0, OPEN_EXISTING,
+                  FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);
+  if (h)
+    {
+      SetFileTime (h, 0, 0, &ftime);
+      CloseHandle (h);
+    }
+}
+
+static FILE *
+common_fopen (char *path)
+{
+  FILE *out;
+  out = fopen (path, "wb");
+  if (!out)
+    {
+      /* maybe we need to create a directory */
+      if (mkdir_p (0, path))
+       {
+         skip_file ();
+         return 0;
+       }
+      out = fopen (path, "wb");
+    }
+  if (!out)
+    {
+      fprintf (stderr, "unable to write to file %s\n", path);
+      perror ("The error was");
+      skip_file ();
+      return 0;
+    }
+  return out;
+}
+
+static void
+prepare_for_file (char *path)
+{
+  DWORD w;
+  mkdir_p (0, path);
+
+  w = GetFileAttributes (path);
+  if (w != 0xffffffff && w & FILE_ATTRIBUTE_DIRECTORY)
+    {
+      char *tmp = (char *) malloc (strlen (path) + 10);
+      int i = 0;
+      do {
+       i++;
+       sprintf (tmp, "%s.old-%d", path, i);
+      } while (GetFileAttributes (tmp) != 0xffffffff);
+      fprintf (stderr, "warning: moving directory \"%s\" out of the way.\n", path);
+      MoveFile (path, tmp);
+      free (tmp);
+    }
+
+  DeleteFileA (path);
+}
+
+int
+tar_read_file (char *path)
+{
+  FILE *out, *copy;
+  HANDLE h;
+  DWORD w;
+  int got;
+  tar_map_result_type *tmr;
+
+  switch (tar_header.typeflag)
+    {
+    case '0':  /* regular files */
+    case 0:
+    case '7':
+      vp (_tar_vfile, "F %s\n", path);
+      prepare_for_file (path);
+      out = common_fopen (path);
+      if (!out)
+       return 1;
+
+      while (file_length > 0)
+       {
+         int put;
+         int want = file_length > 512 ? 512 : file_length;
+         got = gzread (g, buf, 512);
+         if (got < 512)
+           {
+             fprintf (stderr, "tar: unexpected end of file reading %s\n", path);
+             fclose (out);
+             remove (path);
+             return 1;
+           }
+         put = fwrite (buf, 1, want, out);
+         if (put < want)
+           {
+             fprintf (stderr, "tar: out of disk space writing %s\n", path);
+             fclose (out);
+             remove (path);
+             skip_file ();
+             return 1;
+           }
+         file_length -= want;
+       }
+      fclose (out);
+
+      fix_time_stamp (path);
+
+      /* we need this to do hard links below */
+      tmr = (tar_map_result_type *) malloc (sizeof (tar_map_result_type));
+      tmr->next = tar_map_result;
+      tmr->stored_name = xstrdup (file_name);
+      tmr->mapped_name = xstrdup (path);
+      tar_map_result = tmr;
+
+      return 0;
+
+    case '1':  /* hard links; we just copy */
+      for (tmr = tar_map_result; tmr; tmr=tmr->next)
+       if (strcmp (tmr->stored_name, tar_header.linkname) == 0)
+         break;
+      if (!tmr)
+       {
+         fprintf (stderr, "tar: can't find %s to link %s to\n",
+                  tar_header.linkname, path);
+         return 1;
+       }
+      vp (_tar_vfile, "H %s <- %s\n", path, tmr->mapped_name);
+      prepare_for_file (path);
+      copy = fopen (tmr->mapped_name, "rb");
+      if (!copy)
+       {
+         fprintf (stderr, "tar: unable to read %s\n", tmr->mapped_name);
+         return 1;
+       }
+      out = common_fopen (path);
+      if (!out)
+       return 1;
+
+      while ((got = fread (buf, 1, 512, copy)) > 0)
+       {
+         int put = fwrite (buf, 1, got, out);
+         if (put < got)
+           {
+             fprintf (stderr, "tar: out of disk space writing %s\n", path);
+             fclose (out);
+             fclose (copy);
+             remove (path);
+             return 1;
+           }
+       }
+      fclose (out);
+      fclose (copy);
+
+      fix_time_stamp (path);
+      return 0;
+
+    case '5':  /* directories */
+      vp (_tar_vfile, "D %s\n", path);
+      while (path[0] && path[strlen (path)-1] == '/')
+       path[strlen (path) - 1] = 0;
+      return mkdir_p (1, path);
+
+
+    case '2':  /* symbolic links */
+      vp (_tar_vfile, "L %s -> %s\n", path, tar_header.linkname);
+      prepare_for_file (path);
+      h = CreateFileA (path, GENERIC_WRITE, 0, 0, CREATE_NEW,
+                     FILE_ATTRIBUTE_NORMAL, 0);
+      if (h == INVALID_HANDLE_VALUE)
+       {
+         fprintf (stderr, "error: unable to create symlink \"%s\" -> \"%s\"\n",
+                  path, tar_header.linkname);
+         return 1;
+       }
+      strcpy (buf, SYMLINK_COOKIE);
+      strcat (buf, tar_header.linkname);
+      if (WriteFile (h, buf, strlen (buf) + 1, &w, NULL))
+       {
+         CloseHandle (h);
+         SetFileAttributesA (path, FILE_ATTRIBUTE_SYSTEM);
+         return 0;
+       }
+      CloseHandle (h);
+      fprintf (stderr, "error: unable to write symlink \"%s\"\n", path);
+      DeleteFileA (path);
+      return 1;
+    }
+
+  return 0;
+}
+
+int
+tar_close ()
+{
+#if 0
+  while (tar_map_result)
+    {
+      tar_map_result_type *t = tar_map_result->next;
+      free (tar_map_result->stored_name);
+      free (tar_map_result->mapped_name);
+      free (tar_map_result);
+      tar_map_result = t;
+    }
+#endif
+  tar_map_result = 0;
+
+  if (gzclose (g))
+    err ++;
+  return err; /* includes errors for skipped files, etc */
+}
+
+typedef struct {
+  char *from;
+  int from_len;
+  char *to;
+  int to_len;
+} map_type;
+
+static map_type *map;
+static int nmaps;
+
+int
+tar_auto (char *pathname, char **maplist)
+{
+  char *c;
+  int errcount = 0;
+  int i, j;
+  map_type mtemp;
+  char newname[_MAX_PATH+512];
+  static char twiddles[] = "|\b/\b-\b\\\b";
+  int t = 0;
+
+  for (nmaps=0; maplist[nmaps*2]; nmaps++) ;
+  map = (map_type *) malloc ((nmaps+1) * sizeof (map_type));
+  for (nmaps=0; maplist[nmaps*2]; nmaps++)
+    {
+      map[nmaps].from = maplist[nmaps*2];
+      map[nmaps].from_len = strlen (maplist[nmaps*2]);
+      map[nmaps].to = maplist[nmaps*2+1];
+      map[nmaps].to_len = strlen (maplist[nmaps*2+1]);
+    }
+  /* bubble sort - expect the maps to be short */
+  for (i=0; i<nmaps-1; i++)
+    for (j=i+1; j<nmaps; j++)
+      if (map[i].from_len < map[j].from_len)
+       {
+         mtemp = map[i];
+         map[i] = map[j];
+         map[j] = mtemp;
+       }
+
+  if ((tar_open (pathname)))
+    return 1;
+  while (c = tar_next_file ())
+    {
+      int l = strlen (c);
+      for (i=0; i<nmaps; i++)
+       if (l >= map[i].from_len
+           && strncmp (c, map[i].from, map[i].from_len) == 0)
+         {
+           strcpy (newname, map[i].to);
+           strcpy (newname+map[i].to_len, c + map[i].from_len);
+           c = newname;
+           break;
+         }
+
+      t = (t+2) % 8;
+      fwrite (twiddles+t, 1, 2, stderr);
+
+      if (tar_read_file (c))
+       errcount ++;
+    }
+  if (tar_close ())
+    errcount ++;
+
+  fwrite (" \b", 1, 2, stderr);
+
+  vp2 (_tar_vfile, "tar_auto returns %d\n", errcount);
+  return errcount;
+}
diff --git a/netinstall/tar.h b/netinstall/tar.h
new file mode 100644 (file)
index 0000000..e299481
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * 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 __TAR_H_
+#define __TAR_H_
+
+/* Only one tarfile may be open at a time.  gzipped files handled
+   automatically */
+
+/* returns zero on success, nonzero on failure */
+int    tar_open (char *pathname);
+
+/* returns pointer to static buf containing name of next file */
+char * tar_next_file ();
+
+/* byte position in [compressed] file */
+int    tar_ftell ();
+
+/* pass adjusted path, returns zero on success, nonzero on failure */
+int    tar_read_file (char *path);
+
+/* closes the file */
+int    tar_close ();
+
+/* pass path to tar file and from/to pairs for path prefix (NULLs at
+   end , returns zero if completely successful, nonzero (counts
+   errors) on failure */
+int    tar_auto (char *pathname, char **map);
+
+int    tar_mkdir_p (int isadir, char *path);
+
+/*
+extern int _tar_verbose;
+extern FILE * _tar_vfile;
+*/
+
+#endif
diff --git a/netinstall/version.h b/netinstall/version.h
new file mode 100644 (file)
index 0000000..9214dfd
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * 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>
+ *
+ */
+
+/* misc version-related things */
+
+extern "C" char *version;
+extern "C" char *setup_version;
+extern "C" unsigned int setup_timestamp;
+
+extern char *canonicalize_version (char *);
diff --git a/netinstall/version.pl b/netinstall/version.pl
new file mode 100644 (file)
index 0000000..60be739
--- /dev/null
@@ -0,0 +1,6 @@
+while (<STDIN>) {
+  if (/^\$Revision:\s*([0-9\.]*)/) {
+    print "char *version = \"$1\";\n";
+    print "static char *id = \"\\n%%% setup-version $1\\n\";\n";
+  }
+}
diff --git a/netinstall/win32.h b/netinstall/win32.h
new file mode 100644 (file)
index 0000000..d1ee070
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * 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 limit the number of Win32 headers we
+   actually have to parse.  The Setup program only uses a few of them,
+   so there's no point in parsing them all (even lean-n-mean).  Doing
+   this cuts compile time in half. */
+
+#ifndef _MINI_WIN32_
+#define _MINI_WIN32_
+
+#define _UNION_NAME(x)
+#define _STRUCT_NAME(x)
+#define NOCOMATTRIBUTE
+
+#include <stdarg.h>
+#ifdef WIN32_NATIVE
+/* MSVC is barking with the list above, something else is missing, so
+   I'm using <windows.h> and lean-n-mean. FP, 2000-23-12 */
+#include <windows.h>
+#endif
+#include <windef.h>
+#include <basetyps.h>
+#include <winbase.h>
+#include <wingdi.h>
+#include <winuser.h>
+#include <wininet.h>
+#include <winreg.h>
+
+#include <windowsx.h>
+
+/* Cope with native win32 & mingw differences.  Written by F. Popineau
+   <Fabrice.Popineau@supelec.fr> */
+#ifdef WIN32_NATIVE
+#  pragma warning( disable : 4007 4096 4018 4244 )  
+#  define strdup _strdup
+#  define stat _stat
+#  define strnicmp _strnicmp
+#endif
+
+#ifndef CDECL
+#define CDECL __cdecl
+#endif
+
+#endif /* _MINI_WIN32_ */
diff --git a/netinstall/xemacs.ico b/netinstall/xemacs.ico
new file mode 100644 (file)
index 0000000..b067330
Binary files /dev/null and b/netinstall/xemacs.ico differ
diff --git a/tests/redisplay-tests.el b/tests/redisplay-tests.el
new file mode 100644 (file)
index 0000000..1558ebe
--- /dev/null
@@ -0,0 +1,42 @@
+;; Copyright (C) 2000 Free Software Foundation, Inc.
+
+;; Author: Yoshiki Hayashi  <yoshiki@xemacs.org>
+;; Maintainer: Yoshiki Hayashi  <yoshiki@xemacs.org>
+;; Created: 2000
+;; Keywords: tests
+
+;; This file is part of XEmacs.
+
+;; XEmacs 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, or (at your option)
+;; any later version.
+
+;; XEmacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with XEmacs; see the file COPYING.  If not, write to the Free
+;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+;; 02111-1307, USA.
+
+;;; Synched up with: Not in FSF.
+
+;;; Commentary:
+
+;; Redisplay related tests.
+
+;; This used to crash XEmacs.
+(when (featurep 'mule)
+  (let ((buffer (generate-new-buffer "*split test*")))
+    (set-window-buffer (selected-window) buffer)
+    (split-window-vertically)
+    (insert (make-char 'japanese-jisx0208 36 44))
+    (backward-char)
+    (redraw-frame)
+    (delete-other-windows)
+    (split-window)
+    (kill-buffer buffer)
+    (delete-other-windows)))