Initial revision
authortomo <tomo>
Mon, 13 Aug 2001 11:49:00 +0000 (11:49 +0000)
committertomo <tomo>
Mon, 13 Aug 2001 11:49:00 +0000 (11:49 +0000)
79 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.c [new file with mode: 0644]
netinstall/inilex.l [new file with mode: 0644]
netinstall/iniparse.c [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.c b/netinstall/inilex.c
new file mode 100644 (file)
index 0000000..9562b21
--- /dev/null
@@ -0,0 +1,1802 @@
+/* A lexical scanner generated by flex */
+
+/* Scanner skeleton version:
+ * $Header: /usr/CVSroot/XEmacs/xemacs/netinstall/Attic/inilex.c,v 1.1.2.3 2000/12/27 09:35:04 andyp Exp $
+ */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+
+#include <stdio.h>
+
+
+/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+#ifdef c_plusplus
+#ifndef __cplusplus
+#define __cplusplus
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include <stdlib.h>
+#include <unistd.h>
+
+/* Use prototypes in function declarations. */
+#define YY_USE_PROTOS
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else  /* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_PROTOS
+#define YY_USE_CONST
+
+#endif /* __STDC__ */
+#endif /* ! __cplusplus */
+
+#ifdef __TURBOC__
+ #pragma warn -rch
+ #pragma warn -use
+#include <io.h>
+#include <stdlib.h>
+#define YY_USE_CONST
+#define YY_USE_PROTOS
+#endif
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+
+#ifdef YY_USE_PROTOS
+#define YY_PROTO(proto) proto
+#else
+#define YY_PROTO(proto) ()
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#define YY_BUF_SIZE 16384
+
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+
+extern int yyleng;
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+/* The funky do-while in the following #define is used to turn the definition
+ * int a single C statement (which needs a semi-colon terminator).  This
+ * avoids problems with code like:
+ *
+ *     if ( condition_holds )
+ *             yyless( 5 );
+ *     else
+ *             do_something_else();
+ *
+ * Prior to using the do-while the compiler would get upset at the
+ * "else" because it interpreted the "if" statement as being all
+ * done when it reached the ';' after the yyless() call.
+ */
+
+/* Return all but the first 'n' matched characters back to the input stream. */
+
+#define yyless(n) \
+       do \
+               { \
+               /* Undo effects of setting up yytext. */ \
+               *yy_cp = yy_hold_char; \
+               yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
+               YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+               } \
+       while ( 0 )
+
+#define unput(c) yyunput( c, yytext_ptr )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+typedef unsigned int yy_size_t;
+
+
+struct yy_buffer_state
+       {
+       FILE *yy_input_file;
+
+       char *yy_ch_buf;                /* input buffer */
+       char *yy_buf_pos;               /* current position in input buffer */
+
+       /* Size of input buffer in bytes, not including room for EOB
+        * characters.
+        */
+       yy_size_t yy_buf_size;
+
+       /* Number of characters read into yy_ch_buf, not including EOB
+        * characters.
+        */
+       int yy_n_chars;
+
+       /* Whether we "own" the buffer - i.e., we know we created it,
+        * and can realloc() it to grow it, and should free() it to
+        * delete it.
+        */
+       int yy_is_our_buffer;
+
+       /* Whether this is an "interactive" input source; if so, and
+        * if we're using stdio for input, then we want to use getc()
+        * instead of fread(), to make sure we stop fetching input after
+        * each newline.
+        */
+       int yy_is_interactive;
+
+       /* Whether we're considered to be at the beginning of a line.
+        * If so, '^' rules will be active on the next match, otherwise
+        * not.
+        */
+       int yy_at_bol;
+
+       /* Whether to try to fill the input buffer when we reach the
+        * end of it.
+        */
+       int yy_fill_buffer;
+
+       int yy_buffer_status;
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+       /* When an EOF's been seen but there's still some text to process
+        * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+        * shouldn't try reading from the input source any more.  We might
+        * still have a bunch of tokens to match, though, because of
+        * possible backing-up.
+        *
+        * When we actually see the EOF, we change the status to "new"
+        * (via yyrestart()), so that the user can continue scanning by
+        * just pointing yyin at a new input file.
+        */
+#define YY_BUFFER_EOF_PENDING 2
+       };
+
+static YY_BUFFER_STATE yy_current_buffer = 0;
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ */
+#define YY_CURRENT_BUFFER yy_current_buffer
+
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+
+static int yy_n_chars;         /* number of characters read into yy_ch_buf */
+
+
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 1;                /* whether we need to initialize */
+static int yy_start = 0;       /* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart YY_PROTO(( FILE *input_file ));
+
+void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
+void yy_load_buffer_state YY_PROTO(( void ));
+YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
+void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
+void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
+
+YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
+YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *str ));
+YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
+
+static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
+static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
+static void yy_flex_free YY_PROTO(( void * ));
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+       { \
+       if ( ! yy_current_buffer ) \
+               yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+       yy_current_buffer->yy_is_interactive = is_interactive; \
+       }
+
+#define yy_set_bol(at_bol) \
+       { \
+       if ( ! yy_current_buffer ) \
+               yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+       yy_current_buffer->yy_at_bol = at_bol; \
+       }
+
+#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
+
+
+#define YY_USES_REJECT
+
+#define yywrap() 1
+#define YY_SKIP_YYWRAP
+typedef unsigned char YY_CHAR;
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+typedef int yy_state_type;
+extern int yylineno;
+int yylineno = 1;
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state YY_PROTO(( void ));
+static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
+static int yy_get_next_buffer YY_PROTO(( void ));
+static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+       yytext_ptr = yy_bp; \
+       yyleng = (int) (yy_cp - yy_bp); \
+       yy_hold_char = *yy_cp; \
+       *yy_cp = '\0'; \
+       yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 21
+#define YY_END_OF_BUFFER 22
+static yyconst short int yy_acclist[188] =
+    {   0,
+       22,   20,   21,   17,   20,   21,   19,   21,   20,   21,
+       20,   21,   16,   20,   21,   20,   21,   16,   20,   21,
+       16,   20,   21,   16,   20,   21,   16,   20,   21,   16,
+       20,   21,   16,   20,   21,   16,   20,   21,   16,   20,
+       21,   16,   20,   21,   16,   20,   21,   16,   20,   21,
+       17,    1,   18,   16,   16,   16,   16,   16,   16,   16,
+       16,   16,   10,   16,   16,   16,   16,   16,   16,   16,
+       15,   16,   16,   16,   16,   16,   16,   16,   16,   16,
+       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
+       16,   16,   16,   16,   16,   16,   16,   16,   16,   13,
+
+       15,   16,   16,   16,   16,   16,    6,   16,   16,   16,
+       16,   16,   16,    6,   10,   16,   11,   15,   14,   15,
+       12,   15,   16,    9,    8,   16,   16,   16,   16,    9,
+       10,    8,   10,   16,   16,   16,   16,   16,   16,    7,
+       16,   16,   16,   16,    7,   10,   16,    5,   16,   16,
+        4,    5,   10,   16,   16,    4,   10,   16,   16,   16,
+       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
+       16,   16,   16,   16,   16,   16,   16,   16,    3,   16,
+        3,   10,   16,   16,    2,    2,   10
+    } ;
+
+static yyconst short int yy_accept[167] =
+    {   0,
+        1,    1,    1,    2,    4,    7,    9,   11,   13,   16,
+       18,   21,   24,   27,   30,   33,   36,   39,   42,   45,
+       48,   51,   52,   52,   53,   53,   54,   55,   55,   55,
+       55,   55,   55,   56,   57,   58,   59,   60,   61,   62,
+       63,   64,   65,   66,   67,   68,   69,   70,   71,   72,
+       72,   72,   72,   72,   73,   74,   75,   76,   77,   78,
+       79,   80,   81,   82,   83,   84,   85,   86,   86,   86,
+       86,   86,   87,   88,   89,   90,   91,   92,   93,   94,
+       95,   96,   97,   98,   99,  100,  100,  102,  102,  102,
+      103,  104,  105,  106,  107,  108,  109,  110,  111,  112,
+
+      113,  114,  116,  117,  119,  121,  123,  124,  125,  126,
+      127,  128,  129,  130,  132,  134,  135,  136,  137,  138,
+      139,  140,  141,  142,  143,  144,  145,  147,  148,  149,
+      150,  151,  152,  154,  155,  156,  158,  159,  160,  161,
+      162,  163,  164,  165,  166,  167,  168,  169,  170,  171,
+      172,  173,  174,  175,  176,  177,  178,  179,  180,  181,
+      183,  184,  185,  186,  188,  188
+    } ;
+
+static yyconst int yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    1,    2,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    1,    4,    5,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    6,    7,    7,    7,    7,    7,
+        7,    7,    7,    7,    7,    7,    7,    8,    1,    1,
+        1,    1,    1,    1,    7,    7,    7,    7,    7,    7,
+        7,    7,    7,    7,    7,    7,    7,    7,    7,    7,
+        7,    7,    7,    7,    7,    7,    7,    7,    7,    7,
+        9,    1,   10,    1,    7,    1,   11,    7,   12,   13,
+
+       14,    7,    7,    7,   15,    7,    7,   16,   17,   18,
+       19,   20,    7,   21,   22,   23,   24,   25,    7,   26,
+       27,    7,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst int yy_meta[28] =
+    {   0,
+        1,    1,    1,    1,    1,    2,    2,    3,    1,    1,
+        2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
+        2,    2,    2,    2,    2,    2,    2
+    } ;
+
+static yyconst short int yy_base[171] =
+    {   0,
+        0,   27,  264,  265,  261,  265,  258,  258,    0,   43,
+      242,  246,   45,  231,  243,  248,   52,   48,   54,   57,
+       61,  253,  250,  265,  250,  265,    0,  242,   61,   62,
+       66,   64,  229,  236,  235,  225,  223,  226,  224,  236,
+      265,   69,   72,   75,   71,   73,   82,   74,  265,   82,
+       86,   90,   83,  220,  220,  219,  216,  218,  224,  215,
+       90,   93,   99,  100,   91,  102,  101,  101,  226,  104,
+      107,  224,  222,  221,  212,  219,  222,  214,  117,  119,
+      124,  118,  125,  220,  126,  217,  265,  216,  215,  208,
+      215,  214,  215,  206,  265,  200,  127,  210,  209,  112,
+
+      131,  265,  132,  265,  265,  265,  200,  265,  265,  119,
+      207,  196,  138,  265,  265,  139,  205,  140,  204,  196,
+      196,  265,  201,  200,  141,  145,  265,  199,  265,  189,
+      184,  265,  265,  144,  142,  265,  190,  181,  152,  147,
+      180,  186,  149,  157,  177,  180,  159,  160,  187,  179,
+      162,  166,  179,  178,  168,  175,  161,  265,  167,  265,
+      172,  170,  265,  265,  265,  187,  190,  175,  117,  192
+    } ;
+
+static yyconst short int yy_def[171] =
+    {   0,
+      165,  165,  165,  165,  165,  165,  166,  167,  168,  169,
+      168,  168,  168,  168,  168,  170,  170,  170,  170,  170,
+      170,  165,  166,  165,  167,  165,  168,  169,  169,  169,
+      169,  169,  168,  168,  168,  168,  168,  168,  168,  170,
+      165,  170,  170,  170,  170,  170,  170,  170,  165,  169,
+      169,  169,  169,  168,  168,  168,  168,  168,  168,  168,
+      170,  170,  170,  170,  170,  170,  170,  169,  169,  169,
+      169,  168,  168,  168,  168,  168,  168,  168,  170,  170,
+      170,  170,  170,  170,  170,  169,  165,  169,  169,  168,
+      168,  168,  168,  168,  165,  168,  170,  170,  170,  170,
+
+      170,  165,  170,  165,  165,  165,  168,  165,  165,  168,
+      168,  168,  170,  165,  165,  170,  170,  170,  168,  168,
+      168,  165,  168,  170,  170,  170,  165,  170,  165,  168,
+      168,  165,  165,  170,  170,  165,  168,  168,  170,  170,
+      168,  168,  170,  170,  168,  168,  170,  170,  168,  168,
+      170,  170,  168,  168,  170,  170,  168,  165,  170,  165,
+      168,  170,  165,  165,    0,  165,  165,  165,  165,  165
+    } ;
+
+static yyconst short int yy_nxt[293] =
+    {   0,
+        4,    5,    6,    7,    8,    9,    9,    4,   10,    4,
+        9,    9,    9,    9,   11,   12,    9,    9,    9,    9,
+        9,   13,   14,    9,   15,    9,    9,    4,    5,    6,
+        7,    8,   16,   16,    4,   10,    4,   16,   16,   16,
+       16,   17,   18,   16,   16,   16,   16,   16,   19,   20,
+       16,   21,   16,   16,   29,   41,   30,   35,   36,   41,
+       43,   41,   31,   37,   41,   32,   44,   45,   41,   42,
+       49,   49,   46,   49,   48,   49,   41,   53,   41,   41,
+       41,   41,   41,   47,   50,   62,   52,   51,   63,   41,
+       61,   49,   49,   64,   67,   49,   65,   41,   41,   49,
+
+       41,   66,   68,   70,   71,   69,   41,   41,   41,   41,
+       49,   83,   79,   49,   80,   84,   49,  116,   28,   41,
+       81,   86,   85,   82,   41,   41,   41,   97,   88,   89,
+       98,   41,   41,   41,   41,   99,  101,  100,   41,   41,
+      103,  120,  113,  121,  117,   41,   41,   41,   41,   41,
+      118,   41,   41,  124,   41,  134,   41,  128,  135,   41,
+      139,  125,  140,  126,   41,  143,   41,   41,  144,   41,
+      147,  148,  155,   41,   41,   41,   27,  164,  152,  163,
+      161,  151,  160,  156,  159,  158,  162,   23,   23,   23,
+       25,   25,   25,   40,   40,  157,  154,  153,  150,  149,
+
+      146,  145,  142,  141,  138,  137,  136,  133,  132,  131,
+      130,  129,  127,  123,  122,  119,  115,  114,  112,  111,
+      110,  109,  108,  107,  106,  105,  104,  102,   96,   95,
+       94,   93,   92,   91,   90,   87,   78,   77,   76,   75,
+       74,   73,   72,   41,   60,   59,   58,   57,   56,   55,
+       54,   49,   26,   24,   22,   41,   39,   38,   34,   33,
+       26,   24,   22,  165,    3,  165,  165,  165,  165,  165,
+      165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+      165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+      165,  165
+
+    } ;
+
+static yyconst short int yy_chk[293] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    2,    2,    2,
+        2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
+        2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
+        2,    2,    2,    2,   10,   18,   10,   13,   13,   17,
+       18,   19,   10,   13,   20,   10,   19,   19,   21,   17,
+       29,   30,   19,   32,   21,   31,   42,   32,   45,   43,
+       46,   48,   44,   20,   29,   43,   31,   30,   44,   47,
+       42,   50,   53,   45,   48,   51,   46,   61,   65,   52,
+
+       62,   47,   50,   52,   53,   51,   63,   64,   67,   66,
+       68,   65,   61,   70,   62,   66,   71,  100,  169,  100,
+       63,   68,   67,   64,   79,   82,   80,   79,   70,   71,
+       80,   81,   83,   85,   97,   81,   83,   82,  101,  103,
+       85,  110,   97,  110,  101,  113,  116,  118,  125,  135,
+      103,  134,  126,  113,  140,  125,  143,  118,  126,  139,
+      134,  116,  135,  116,  144,  139,  147,  148,  140,  151,
+      143,  144,  151,  152,  159,  155,  168,  162,  148,  161,
+      157,  147,  156,  152,  155,  154,  159,  166,  166,  166,
+      167,  167,  167,  170,  170,  153,  150,  149,  146,  145,
+
+      142,  141,  138,  137,  131,  130,  128,  124,  123,  121,
+      120,  119,  117,  112,  111,  107,   99,   98,   96,   94,
+       93,   92,   91,   90,   89,   88,   86,   84,   78,   77,
+       76,   75,   74,   73,   72,   69,   60,   59,   58,   57,
+       56,   55,   54,   40,   39,   38,   37,   36,   35,   34,
+       33,   28,   25,   23,   22,   16,   15,   14,   12,   11,
+        8,    7,    5,    3,  165,  165,  165,  165,  165,  165,
+      165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+      165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
+      165,  165
+
+    } ;
+
+static yy_state_type yy_state_buf[YY_BUF_SIZE + 2], *yy_state_ptr;
+static char *yy_full_match;
+static int yy_lp;
+#define REJECT \
+{ \
+*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ \
+yy_cp = yy_full_match; /* restore poss. backed-over text */ \
+++yy_lp; \
+goto find_rule; \
+}
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+char *yytext;
+#line 1 "/windows/build/xemacs/xemacs/netinstall/inilex.l"
+#define INITIAL 0
+#line 2 "/windows/build/xemacs/xemacs/netinstall/inilex.l"
+/*
+ * 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 */
+#define YY_NEVER_INTERACTIVE 1
+#line 546 "lex.yy.c"
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap YY_PROTO(( void ));
+#else
+extern int yywrap YY_PROTO(( void ));
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+static void yyunput YY_PROTO(( int c, char *buf_ptr ));
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput YY_PROTO(( void ));
+#else
+static int input YY_PROTO(( void ));
+#endif
+#endif
+
+#if YY_STACK_USED
+static int yy_start_stack_ptr = 0;
+static int yy_start_stack_depth = 0;
+static int *yy_start_stack = 0;
+#ifndef YY_NO_PUSH_STATE
+static void yy_push_state YY_PROTO(( int new_state ));
+#endif
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state YY_PROTO(( void ));
+#endif
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state YY_PROTO(( void ));
+#endif
+
+#else
+#define YY_NO_PUSH_STATE 1
+#define YY_NO_POP_STATE 1
+#define YY_NO_TOP_STATE 1
+#endif
+
+#ifdef YY_MALLOC_DECL
+YY_MALLOC_DECL
+#else
+#if __STDC__
+#ifndef __cplusplus
+#include <stdlib.h>
+#endif
+#else
+/* Just try to get by without declaring the routines.  This will fail
+ * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
+ * or sizeof(void*) != sizeof(int).
+ */
+#endif
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+       if ( yy_current_buffer->yy_is_interactive ) \
+               { \
+               int c = '*', n; \
+               for ( n = 0; n < max_size && \
+                            (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+                       buf[n] = (char) c; \
+               if ( c == '\n' ) \
+                       buf[n++] = (char) c; \
+               if ( c == EOF && ferror( yyin ) ) \
+                       YY_FATAL_ERROR( "input in flex scanner failed" ); \
+               result = n; \
+               } \
+       else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \
+                 && ferror( yyin ) ) \
+               YY_FATAL_ERROR( "input in flex scanner failed" );
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL int yylex YY_PROTO(( void ))
+#endif
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+       if ( yyleng > 0 ) \
+               yy_current_buffer->yy_at_bol = \
+                               (yytext[yyleng - 1] == '\n'); \
+       YY_USER_ACTION
+
+YY_DECL
+       {
+       register yy_state_type yy_current_state;
+       register char *yy_cp, *yy_bp;
+       register int yy_act;
+
+#line 42 "/windows/build/xemacs/xemacs/netinstall/inilex.l"
+
+
+#line 699 "lex.yy.c"
+
+       if ( yy_init )
+               {
+               yy_init = 0;
+
+#ifdef YY_USER_INIT
+               YY_USER_INIT;
+#endif
+
+               if ( ! yy_start )
+                       yy_start = 1;   /* first start state */
+
+               if ( ! yyin )
+                       yyin = stdin;
+
+               if ( ! yyout )
+                       yyout = stdout;
+
+               if ( ! yy_current_buffer )
+                       yy_current_buffer =
+                               yy_create_buffer( yyin, YY_BUF_SIZE );
+
+               yy_load_buffer_state();
+               }
+
+       while ( 1 )             /* loops until end-of-file is reached */
+               {
+               yy_cp = yy_c_buf_p;
+
+               /* Support of yytext. */
+               *yy_cp = yy_hold_char;
+
+               /* yy_bp points to the position in yy_ch_buf of the start of
+                * the current run.
+                */
+               yy_bp = yy_cp;
+
+               yy_current_state = yy_start;
+               yy_current_state += YY_AT_BOL();
+               yy_state_ptr = yy_state_buf;
+               *yy_state_ptr++ = yy_current_state;
+yy_match:
+               do
+                       {
+                       register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+                       while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+                               {
+                               yy_current_state = (int) yy_def[yy_current_state];
+                               if ( yy_current_state >= 166 )
+                                       yy_c = yy_meta[(unsigned int) yy_c];
+                               }
+                       yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+                       *yy_state_ptr++ = yy_current_state;
+                       ++yy_cp;
+                       }
+               while ( yy_base[yy_current_state] != 265 );
+
+yy_find_action:
+               yy_current_state = *--yy_state_ptr;
+               yy_lp = yy_accept[yy_current_state];
+find_rule: /* we branch to this label when backing up */
+               for ( ; ; ) /* until we find what rule we matched */
+                       {
+                       if ( yy_lp && yy_lp < yy_accept[yy_current_state + 1] )
+                               {
+                               yy_act = yy_acclist[yy_lp];
+                                       {
+                                       yy_full_match = yy_cp;
+                                       break;
+                                       }
+                               }
+                       --yy_cp;
+                       yy_current_state = *--yy_state_ptr;
+                       yy_lp = yy_accept[yy_current_state];
+                       }
+
+               YY_DO_BEFORE_ACTION;
+
+               if ( yy_act != YY_END_OF_BUFFER )
+                       {
+                       int yyl;
+                       for ( yyl = 0; yyl < yyleng; ++yyl )
+                               if ( yytext[yyl] == '\n' )
+                                       ++yylineno;
+                       }
+
+do_action:     /* This label is used only to access EOF actions. */
+
+
+               switch ( yy_act )
+       { /* beginning of action switch */
+case 1:
+YY_RULE_SETUP
+#line 44 "/windows/build/xemacs/xemacs/netinstall/inilex.l"
+{ yylval = strdup (yytext+1);
+                         yylval[strlen (yylval)-1] = 0;
+                         return STRING; }
+       YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 48 "/windows/build/xemacs/xemacs/netinstall/inilex.l"
+return SETUP_TIMESTAMP;
+       YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 49 "/windows/build/xemacs/xemacs/netinstall/inilex.l"
+return SETUP_VERSION;
+       YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 50 "/windows/build/xemacs/xemacs/netinstall/inilex.l"
+return VERSION;
+       YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 51 "/windows/build/xemacs/xemacs/netinstall/inilex.l"
+return INSTALL;
+       YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 52 "/windows/build/xemacs/xemacs/netinstall/inilex.l"
+return TYPE;
+       YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 53 "/windows/build/xemacs/xemacs/netinstall/inilex.l"
+return SOURCE;
+       YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 54 "/windows/build/xemacs/xemacs/netinstall/inilex.l"
+return SDESC;
+       YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 55 "/windows/build/xemacs/xemacs/netinstall/inilex.l"
+return LDESC;
+       YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 57 "/windows/build/xemacs/xemacs/netinstall/inilex.l"
+ignore_line ();
+       YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 59 "/windows/build/xemacs/xemacs/netinstall/inilex.l"
+return T_CURR;
+       YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 60 "/windows/build/xemacs/xemacs/netinstall/inilex.l"
+return T_TEST;
+       YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 61 "/windows/build/xemacs/xemacs/netinstall/inilex.l"
+return T_TEST;
+       YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 62 "/windows/build/xemacs/xemacs/netinstall/inilex.l"
+return T_PREV;
+       YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 63 "/windows/build/xemacs/xemacs/netinstall/inilex.l"
+return T_UNKNOWN;
+       YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 65 "/windows/build/xemacs/xemacs/netinstall/inilex.l"
+{ yylval = strdup (yytext);
+                         return STRING; }
+       YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 68 "/windows/build/xemacs/xemacs/netinstall/inilex.l"
+/* do nothing */
+       YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 70 "/windows/build/xemacs/xemacs/netinstall/inilex.l"
+/* ignore comments */
+       YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 72 "/windows/build/xemacs/xemacs/netinstall/inilex.l"
+{ return yytext[0]; }
+       YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 73 "/windows/build/xemacs/xemacs/netinstall/inilex.l"
+{ return yytext[0]; }
+       YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 75 "/windows/build/xemacs/xemacs/netinstall/inilex.l"
+ECHO;
+       YY_BREAK
+#line 899 "lex.yy.c"
+                       case YY_STATE_EOF(INITIAL):
+                               yyterminate();
+
+       case YY_END_OF_BUFFER:
+               {
+               /* Amount of text matched not including the EOB char. */
+               int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;
+
+               /* Undo the effects of YY_DO_BEFORE_ACTION. */
+               *yy_cp = yy_hold_char;
+
+               if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
+                       {
+                       /* We're scanning a new file or input source.  It's
+                        * possible that this happened because the user
+                        * just pointed yyin at a new source and called
+                        * yylex().  If so, then we have to assure
+                        * consistency between yy_current_buffer and our
+                        * globals.  Here is the right place to do so, because
+                        * this is the first action (other than possibly a
+                        * back-up) that will match for the new input source.
+                        */
+                       yy_n_chars = yy_current_buffer->yy_n_chars;
+                       yy_current_buffer->yy_input_file = yyin;
+                       yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
+                       }
+
+               /* Note that here we test for yy_c_buf_p "<=" to the position
+                * of the first EOB in the buffer, since yy_c_buf_p will
+                * already have been incremented past the NUL character
+                * (since all states make transitions on EOB to the
+                * end-of-buffer state).  Contrast this with the test
+                * in input().
+                */
+               if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+                       { /* This was really a NUL. */
+                       yy_state_type yy_next_state;
+
+                       yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
+
+                       yy_current_state = yy_get_previous_state();
+
+                       /* Okay, we're now positioned to make the NUL
+                        * transition.  We couldn't have
+                        * yy_get_previous_state() go ahead and do it
+                        * for us because it doesn't know how to deal
+                        * with the possibility of jamming (and we don't
+                        * want to build jamming into it because then it
+                        * will run more slowly).
+                        */
+
+                       yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+                       yy_bp = yytext_ptr + YY_MORE_ADJ;
+
+                       if ( yy_next_state )
+                               {
+                               /* Consume the NUL. */
+                               yy_cp = ++yy_c_buf_p;
+                               yy_current_state = yy_next_state;
+                               goto yy_match;
+                               }
+
+                       else
+                               {
+                               yy_cp = yy_c_buf_p;
+                               goto yy_find_action;
+                               }
+                       }
+
+               else switch ( yy_get_next_buffer() )
+                       {
+                       case EOB_ACT_END_OF_FILE:
+                               {
+                               yy_did_buffer_switch_on_eof = 0;
+
+                               if ( yywrap() )
+                                       {
+                                       /* Note: because we've taken care in
+                                        * yy_get_next_buffer() to have set up
+                                        * yytext, we can now set up
+                                        * yy_c_buf_p so that if some total
+                                        * hoser (like flex itself) wants to
+                                        * call the scanner after we return the
+                                        * YY_NULL, it'll still work - another
+                                        * YY_NULL will get returned.
+                                        */
+                                       yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
+
+                                       yy_act = YY_STATE_EOF(YY_START);
+                                       goto do_action;
+                                       }
+
+                               else
+                                       {
+                                       if ( ! yy_did_buffer_switch_on_eof )
+                                               YY_NEW_FILE;
+                                       }
+                               break;
+                               }
+
+                       case EOB_ACT_CONTINUE_SCAN:
+                               yy_c_buf_p =
+                                       yytext_ptr + yy_amount_of_matched_text;
+
+                               yy_current_state = yy_get_previous_state();
+
+                               yy_cp = yy_c_buf_p;
+                               yy_bp = yytext_ptr + YY_MORE_ADJ;
+                               goto yy_match;
+
+                       case EOB_ACT_LAST_MATCH:
+                               yy_c_buf_p =
+                               &yy_current_buffer->yy_ch_buf[yy_n_chars];
+
+                               yy_current_state = yy_get_previous_state();
+
+                               yy_cp = yy_c_buf_p;
+                               yy_bp = yytext_ptr + YY_MORE_ADJ;
+                               goto yy_find_action;
+                       }
+               break;
+               }
+
+       default:
+               YY_FATAL_ERROR(
+                       "fatal flex scanner internal error--no action found" );
+       } /* end of action switch */
+               } /* end of scanning one token */
+       } /* end of yylex */
+
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *     EOB_ACT_LAST_MATCH -
+ *     EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *     EOB_ACT_END_OF_FILE - end of file
+ */
+
+static int yy_get_next_buffer()
+       {
+       register char *dest = yy_current_buffer->yy_ch_buf;
+       register char *source = yytext_ptr;
+       register int number_to_move, i;
+       int ret_val;
+
+       if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
+               YY_FATAL_ERROR(
+               "fatal flex scanner internal error--end of buffer missed" );
+
+       if ( yy_current_buffer->yy_fill_buffer == 0 )
+               { /* Don't try to fill the buffer, so this is an EOF. */
+               if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
+                       {
+                       /* We matched a singled characater, the EOB, so
+                        * treat this as a final EOF.
+                        */
+                       return EOB_ACT_END_OF_FILE;
+                       }
+
+               else
+                       {
+                       /* We matched some text prior to the EOB, first
+                        * process it.
+                        */
+                       return EOB_ACT_LAST_MATCH;
+                       }
+               }
+
+       /* Try to read more data. */
+
+       /* First move last chars to start of buffer. */
+       number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1;
+
+       for ( i = 0; i < number_to_move; ++i )
+               *(dest++) = *(source++);
+
+       if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+               /* don't do the read, it's not guaranteed to return an EOF,
+                * just force an EOF
+                */
+               yy_n_chars = 0;
+
+       else
+               {
+               int num_to_read =
+                       yy_current_buffer->yy_buf_size - number_to_move - 1;
+
+               while ( num_to_read <= 0 )
+                       { /* Not enough room in the buffer - grow it. */
+#ifdef YY_USES_REJECT
+                       YY_FATAL_ERROR(
+"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+#else
+
+                       /* just a shorter name for the current buffer */
+                       YY_BUFFER_STATE b = yy_current_buffer;
+
+                       int yy_c_buf_p_offset =
+                               (int) (yy_c_buf_p - b->yy_ch_buf);
+
+                       if ( b->yy_is_our_buffer )
+                               {
+                               int new_size = b->yy_buf_size * 2;
+
+                               if ( new_size <= 0 )
+                                       b->yy_buf_size += b->yy_buf_size / 8;
+                               else
+                                       b->yy_buf_size *= 2;
+
+                               b->yy_ch_buf = (char *)
+                                       /* Include room in for 2 EOB chars. */
+                                       yy_flex_realloc( (void *) b->yy_ch_buf,
+                                                        b->yy_buf_size + 2 );
+                               }
+                       else
+                               /* Can't grow it, we don't own it. */
+                               b->yy_ch_buf = 0;
+
+                       if ( ! b->yy_ch_buf )
+                               YY_FATAL_ERROR(
+                               "fatal error - scanner input buffer overflow" );
+
+                       yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+                       num_to_read = yy_current_buffer->yy_buf_size -
+                                               number_to_move - 1;
+#endif
+                       }
+
+               if ( num_to_read > YY_READ_BUF_SIZE )
+                       num_to_read = YY_READ_BUF_SIZE;
+
+               /* Read in more data. */
+               YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
+                       yy_n_chars, num_to_read );
+               }
+
+       if ( yy_n_chars == 0 )
+               {
+               if ( number_to_move == YY_MORE_ADJ )
+                       {
+                       ret_val = EOB_ACT_END_OF_FILE;
+                       yyrestart( yyin );
+                       }
+
+               else
+                       {
+                       ret_val = EOB_ACT_LAST_MATCH;
+                       yy_current_buffer->yy_buffer_status =
+                               YY_BUFFER_EOF_PENDING;
+                       }
+               }
+
+       else
+               ret_val = EOB_ACT_CONTINUE_SCAN;
+
+       yy_n_chars += number_to_move;
+       yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+       yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+       yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
+
+       return ret_val;
+       }
+
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+static yy_state_type yy_get_previous_state()
+       {
+       register yy_state_type yy_current_state;
+       register char *yy_cp;
+
+       yy_current_state = yy_start;
+       yy_current_state += YY_AT_BOL();
+       yy_state_ptr = yy_state_buf;
+       *yy_state_ptr++ = yy_current_state;
+
+       for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
+               {
+               register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+               while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+                       {
+                       yy_current_state = (int) yy_def[yy_current_state];
+                       if ( yy_current_state >= 166 )
+                               yy_c = yy_meta[(unsigned int) yy_c];
+                       }
+               yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+               *yy_state_ptr++ = yy_current_state;
+               }
+
+       return yy_current_state;
+       }
+
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *     next_state = yy_try_NUL_trans( current_state );
+ */
+
+#ifdef YY_USE_PROTOS
+static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
+#else
+static yy_state_type yy_try_NUL_trans( yy_current_state )
+yy_state_type yy_current_state;
+#endif
+       {
+       register int yy_is_jam;
+
+       register YY_CHAR yy_c = 1;
+       while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+               {
+               yy_current_state = (int) yy_def[yy_current_state];
+               if ( yy_current_state >= 166 )
+                       yy_c = yy_meta[(unsigned int) yy_c];
+               }
+       yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+       *yy_state_ptr++ = yy_current_state;
+       yy_is_jam = (yy_current_state == 165);
+
+       return yy_is_jam ? 0 : yy_current_state;
+       }
+
+
+#ifndef YY_NO_UNPUT
+#ifdef YY_USE_PROTOS
+static void yyunput( int c, register char *yy_bp )
+#else
+static void yyunput( c, yy_bp )
+int c;
+register char *yy_bp;
+#endif
+       {
+       register char *yy_cp = yy_c_buf_p;
+
+       /* undo effects of setting up yytext */
+       *yy_cp = yy_hold_char;
+
+       if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+               { /* need to shift things up to make room */
+               /* +2 for EOB chars. */
+               register int number_to_move = yy_n_chars + 2;
+               register char *dest = &yy_current_buffer->yy_ch_buf[
+                                       yy_current_buffer->yy_buf_size + 2];
+               register char *source =
+                               &yy_current_buffer->yy_ch_buf[number_to_move];
+
+               while ( source > yy_current_buffer->yy_ch_buf )
+                       *--dest = *--source;
+
+               yy_cp += (int) (dest - source);
+               yy_bp += (int) (dest - source);
+               yy_n_chars = yy_current_buffer->yy_buf_size;
+
+               if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+                       YY_FATAL_ERROR( "flex scanner push-back overflow" );
+               }
+
+       *--yy_cp = (char) c;
+
+       if ( c == '\n' )
+               --yylineno;
+
+       yytext_ptr = yy_bp;
+       yy_hold_char = *yy_cp;
+       yy_c_buf_p = yy_cp;
+       }
+#endif /* ifndef YY_NO_UNPUT */
+
+
+#ifdef __cplusplus
+static int yyinput()
+#else
+static int input()
+#endif
+       {
+       int c;
+
+       *yy_c_buf_p = yy_hold_char;
+
+       if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+               {
+               /* yy_c_buf_p now points to the character we want to return.
+                * If this occurs *before* the EOB characters, then it's a
+                * valid NUL; if not, then we've hit the end of the buffer.
+                */
+               if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+                       /* This was really a NUL. */
+                       *yy_c_buf_p = '\0';
+
+               else
+                       { /* need more input */
+                       yytext_ptr = yy_c_buf_p;
+                       ++yy_c_buf_p;
+
+                       switch ( yy_get_next_buffer() )
+                               {
+                               case EOB_ACT_END_OF_FILE:
+                                       {
+                                       if ( yywrap() )
+                                               {
+                                               yy_c_buf_p =
+                                               yytext_ptr + YY_MORE_ADJ;
+                                               return EOF;
+                                               }
+
+                                       if ( ! yy_did_buffer_switch_on_eof )
+                                               YY_NEW_FILE;
+#ifdef __cplusplus
+                                       return yyinput();
+#else
+                                       return input();
+#endif
+                                       }
+
+                               case EOB_ACT_CONTINUE_SCAN:
+                                       yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
+                                       break;
+
+                               case EOB_ACT_LAST_MATCH:
+#ifdef __cplusplus
+                                       YY_FATAL_ERROR(
+                                       "unexpected last match in yyinput()" );
+#else
+                                       YY_FATAL_ERROR(
+                                       "unexpected last match in input()" );
+#endif
+                               }
+                       }
+               }
+
+       c = *(unsigned char *) yy_c_buf_p;      /* cast for 8-bit char's */
+       *yy_c_buf_p = '\0';     /* preserve yytext */
+       yy_hold_char = *++yy_c_buf_p;
+
+       yy_current_buffer->yy_at_bol = (c == '\n');
+       if ( yy_current_buffer->yy_at_bol )
+               ++yylineno;
+
+       return c;
+       }
+
+
+#ifdef YY_USE_PROTOS
+void yyrestart( FILE *input_file )
+#else
+void yyrestart( input_file )
+FILE *input_file;
+#endif
+       {
+       if ( ! yy_current_buffer )
+               yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
+
+       yy_init_buffer( yy_current_buffer, input_file );
+       yy_load_buffer_state();
+       }
+
+
+#ifdef YY_USE_PROTOS
+void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+#else
+void yy_switch_to_buffer( new_buffer )
+YY_BUFFER_STATE new_buffer;
+#endif
+       {
+       if ( yy_current_buffer == new_buffer )
+               return;
+
+       if ( yy_current_buffer )
+               {
+               /* Flush out information for old buffer. */
+               *yy_c_buf_p = yy_hold_char;
+               yy_current_buffer->yy_buf_pos = yy_c_buf_p;
+               yy_current_buffer->yy_n_chars = yy_n_chars;
+               }
+
+       yy_current_buffer = new_buffer;
+       yy_load_buffer_state();
+
+       /* We don't actually know whether we did this switch during
+        * EOF (yywrap()) processing, but the only time this flag
+        * is looked at is after yywrap() is called, so it's safe
+        * to go ahead and always set it.
+        */
+       yy_did_buffer_switch_on_eof = 1;
+       }
+
+
+#ifdef YY_USE_PROTOS
+void yy_load_buffer_state( void )
+#else
+void yy_load_buffer_state()
+#endif
+       {
+       yy_n_chars = yy_current_buffer->yy_n_chars;
+       yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
+       yyin = yy_current_buffer->yy_input_file;
+       yy_hold_char = *yy_c_buf_p;
+       }
+
+
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
+#else
+YY_BUFFER_STATE yy_create_buffer( file, size )
+FILE *file;
+int size;
+#endif
+       {
+       YY_BUFFER_STATE b;
+
+       b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+       if ( ! b )
+               YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+       b->yy_buf_size = size;
+
+       /* yy_ch_buf has to be 2 characters longer than the size given because
+        * we need to put in 2 end-of-buffer characters.
+        */
+       b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
+       if ( ! b->yy_ch_buf )
+               YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+       b->yy_is_our_buffer = 1;
+
+       yy_init_buffer( b, file );
+
+       return b;
+       }
+
+
+#ifdef YY_USE_PROTOS
+void yy_delete_buffer( YY_BUFFER_STATE b )
+#else
+void yy_delete_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+       {
+       if ( ! b )
+               return;
+
+       if ( b == yy_current_buffer )
+               yy_current_buffer = (YY_BUFFER_STATE) 0;
+
+       if ( b->yy_is_our_buffer )
+               yy_flex_free( (void *) b->yy_ch_buf );
+
+       yy_flex_free( (void *) b );
+       }
+
+
+#ifndef YY_ALWAYS_INTERACTIVE
+#ifndef YY_NEVER_INTERACTIVE
+extern int isatty YY_PROTO(( int ));
+#endif
+#endif
+
+#ifdef YY_USE_PROTOS
+void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
+#else
+void yy_init_buffer( b, file )
+YY_BUFFER_STATE b;
+FILE *file;
+#endif
+
+
+       {
+       yy_flush_buffer( b );
+
+       b->yy_input_file = file;
+       b->yy_fill_buffer = 1;
+
+#if YY_ALWAYS_INTERACTIVE
+       b->yy_is_interactive = 1;
+#else
+#if YY_NEVER_INTERACTIVE
+       b->yy_is_interactive = 0;
+#else
+       b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+#endif
+#endif
+       }
+
+
+#ifdef YY_USE_PROTOS
+void yy_flush_buffer( YY_BUFFER_STATE b )
+#else
+void yy_flush_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+
+       {
+       b->yy_n_chars = 0;
+
+       /* We always need two end-of-buffer characters.  The first causes
+        * a transition to the end-of-buffer state.  The second causes
+        * a jam in that state.
+        */
+       b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+       b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+       b->yy_buf_pos = &b->yy_ch_buf[0];
+
+       b->yy_at_bol = 1;
+       b->yy_buffer_status = YY_BUFFER_NEW;
+
+       if ( b == yy_current_buffer )
+               yy_load_buffer_state();
+       }
+
+
+#ifndef YY_NO_SCAN_BUFFER
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
+#else
+YY_BUFFER_STATE yy_scan_buffer( base, size )
+char *base;
+yy_size_t size;
+#endif
+       {
+       YY_BUFFER_STATE b;
+
+       if ( size < 2 ||
+            base[size-2] != YY_END_OF_BUFFER_CHAR ||
+            base[size-1] != YY_END_OF_BUFFER_CHAR )
+               /* They forgot to leave room for the EOB's. */
+               return 0;
+
+       b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+       if ( ! b )
+               YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+       b->yy_buf_size = size - 2;      /* "- 2" to take care of EOB's */
+       b->yy_buf_pos = b->yy_ch_buf = base;
+       b->yy_is_our_buffer = 0;
+       b->yy_input_file = 0;
+       b->yy_n_chars = b->yy_buf_size;
+       b->yy_is_interactive = 0;
+       b->yy_at_bol = 1;
+       b->yy_fill_buffer = 0;
+       b->yy_buffer_status = YY_BUFFER_NEW;
+
+       yy_switch_to_buffer( b );
+
+       return b;
+       }
+#endif
+
+
+#ifndef YY_NO_SCAN_STRING
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_string( yyconst char *str )
+#else
+YY_BUFFER_STATE yy_scan_string( str )
+yyconst char *str;
+#endif
+       {
+       int len;
+       for ( len = 0; str[len]; ++len )
+               ;
+
+       return yy_scan_bytes( str, len );
+       }
+#endif
+
+
+#ifndef YY_NO_SCAN_BYTES
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
+#else
+YY_BUFFER_STATE yy_scan_bytes( bytes, len )
+yyconst char *bytes;
+int len;
+#endif
+       {
+       YY_BUFFER_STATE b;
+       char *buf;
+       yy_size_t n;
+       int i;
+
+       /* Get memory for full buffer, including space for trailing EOB's. */
+       n = len + 2;
+       buf = (char *) yy_flex_alloc( n );
+       if ( ! buf )
+               YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+       for ( i = 0; i < len; ++i )
+               buf[i] = bytes[i];
+
+       buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+
+       b = yy_scan_buffer( buf, n );
+       if ( ! b )
+               YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+       /* It's okay to grow etc. this buffer, and we should throw it
+        * away when we're done.
+        */
+       b->yy_is_our_buffer = 1;
+
+       return b;
+       }
+#endif
+
+
+#ifndef YY_NO_PUSH_STATE
+#ifdef YY_USE_PROTOS
+static void yy_push_state( int new_state )
+#else
+static void yy_push_state( new_state )
+int new_state;
+#endif
+       {
+       if ( yy_start_stack_ptr >= yy_start_stack_depth )
+               {
+               yy_size_t new_size;
+
+               yy_start_stack_depth += YY_START_STACK_INCR;
+               new_size = yy_start_stack_depth * sizeof( int );
+
+               if ( ! yy_start_stack )
+                       yy_start_stack = (int *) yy_flex_alloc( new_size );
+
+               else
+                       yy_start_stack = (int *) yy_flex_realloc(
+                                       (void *) yy_start_stack, new_size );
+
+               if ( ! yy_start_stack )
+                       YY_FATAL_ERROR(
+                       "out of memory expanding start-condition stack" );
+               }
+
+       yy_start_stack[yy_start_stack_ptr++] = YY_START;
+
+       BEGIN(new_state);
+       }
+#endif
+
+
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state()
+       {
+       if ( --yy_start_stack_ptr < 0 )
+               YY_FATAL_ERROR( "start-condition stack underflow" );
+
+       BEGIN(yy_start_stack[yy_start_stack_ptr]);
+       }
+#endif
+
+
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state()
+       {
+       return yy_start_stack[yy_start_stack_ptr - 1];
+       }
+#endif
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+#ifdef YY_USE_PROTOS
+static void yy_fatal_error( yyconst char msg[] )
+#else
+static void yy_fatal_error( msg )
+char msg[];
+#endif
+       {
+       (void) fprintf( stderr, "%s\n", msg );
+       exit( YY_EXIT_FAILURE );
+       }
+
+
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+       do \
+               { \
+               /* Undo effects of setting up yytext. */ \
+               yytext[yyleng] = yy_hold_char; \
+               yy_c_buf_p = yytext + n - YY_MORE_ADJ; \
+               yy_hold_char = *yy_c_buf_p; \
+               *yy_c_buf_p = '\0'; \
+               yyleng = n; \
+               } \
+       while ( 0 )
+
+
+/* Internal utility routines. */
+
+#ifndef yytext_ptr
+#ifdef YY_USE_PROTOS
+static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
+#else
+static void yy_flex_strncpy( s1, s2, n )
+char *s1;
+yyconst char *s2;
+int n;
+#endif
+       {
+       register int i;
+       for ( i = 0; i < n; ++i )
+               s1[i] = s2[i];
+       }
+#endif
+
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_alloc( yy_size_t size )
+#else
+static void *yy_flex_alloc( size )
+yy_size_t size;
+#endif
+       {
+       return (void *) malloc( size );
+       }
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_realloc( void *ptr, yy_size_t size )
+#else
+static void *yy_flex_realloc( ptr, size )
+void *ptr;
+yy_size_t size;
+#endif
+       {
+       /* The cast to (char *) in the following accommodates both
+        * implementations that use char* generic pointers, and those
+        * that use void* generic pointers.  It works with the latter
+        * because both ANSI C and C++ allow castless assignment from
+        * any pointer type to void*, and deal with argument conversions
+        * as though doing an assignment.
+        */
+       return (void *) realloc( (char *) ptr, size );
+       }
+
+#ifdef YY_USE_PROTOS
+static void yy_flex_free( void *ptr )
+#else
+static void yy_flex_free( ptr )
+void *ptr;
+#endif
+       {
+       free( ptr );
+       }
+
+#if YY_MAIN
+int main()
+       {
+       yylex();
+       return 0;
+       }
+#endif
+#line 75 "/windows/build/xemacs/xemacs/netinstall/inilex.l"
+
+
+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/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.c b/netinstall/iniparse.c
new file mode 100644 (file)
index 0000000..7c30c67
--- /dev/null
@@ -0,0 +1,1068 @@
+
+/*  A Bison parser, made from /windows/build/xemacs/xemacs/netinstall/iniparse.y
+    by GNU Bison version 1.28  */
+
+#define YYBISON 1  /* Identify Bison output.  */
+
+#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
+
+#line 1 "/windows/build/xemacs/xemacs/netinstall/iniparse.y"
+
+/*
+ * 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)
+
+#ifndef YYSTYPE
+#define YYSTYPE int
+#endif
+#include <stdio.h>
+
+#ifndef __cplusplus
+#ifndef __STDC__
+#define const
+#endif
+#endif
+
+
+
+#define        YYFINAL         47
+#define        YYFLAG          -32768
+#define        YYNTBASE        18
+
+#define YYTRANSLATE(x) ((unsigned)(x) <= 269 ? yytranslate[x] : 27)
+
+static const char yytranslate[] = {     0,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,    16,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,    17,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     1,     3,     4,     5,     6,
+     7,     8,     9,    10,    11,    12,    13,    14,    15
+};
+
+#if YYDEBUG != 0
+static const short yyprhs[] = {     0,
+     0,     3,     6,     7,    11,    15,    17,    18,    22,    25,
+    26,    27,    33,    37,    39,    42,    45,    48,    52,    56,
+    59,    61,    63,    65,    67,    68
+};
+
+static const short yyrhs[] = {    19,
+    22,     0,    20,    19,     0,     0,     4,     3,    16,     0,
+     5,     3,    16,     0,    16,     0,     0,     1,    21,    16,
+     0,    23,    22,     0,     0,     0,    17,     3,    16,    24,
+    25,     0,    26,    16,    25,     0,    26,     0,     6,     3,
+     0,     9,     3,     0,    10,     3,     0,     7,     3,     3,
+     0,     8,     3,     3,     0,    11,     3,     0,    12,     0,
+    13,     0,    14,     0,    15,     0,     0,     1,    16,     0
+};
+
+#endif
+
+#if YYDEBUG != 0
+static const short yyrline[] = { 0,
+    50,    54,    55,    59,    60,    61,    62,    63,    66,    67,
+    71,    73,    76,    77,    81,    82,    83,    84,    86,    88,
+    94,    95,    96,    97,    98,    99
+};
+#endif
+
+
+#if YYDEBUG != 0 || defined (YYERROR_VERBOSE)
+
+static const char * const yytname[] = {   "$","error","$undefined.","STRING",
+"SETUP_TIMESTAMP","SETUP_VERSION","VERSION","INSTALL","SOURCE","SDESC","LDESC",
+"TYPE","T_PREV","T_CURR","T_TEST","T_UNKNOWN","'\\n'","'@'","whole_file","setup_headers",
+"setup_header","@1","packages","package","@2","lines","simple_line", NULL
+};
+#endif
+
+static const short yyr1[] = {     0,
+    18,    19,    19,    20,    20,    20,    21,    20,    22,    22,
+    24,    23,    25,    25,    26,    26,    26,    26,    26,    26,
+    26,    26,    26,    26,    26,    26
+};
+
+static const short yyr2[] = {     0,
+     2,     2,     0,     3,     3,     1,     0,     3,     2,     0,
+     0,     5,     3,     1,     2,     2,     2,     3,     3,     2,
+     1,     1,     1,     1,     0,     2
+};
+
+static const short yydefact[] = {     0,
+     7,     0,     0,     6,    10,     0,     0,     0,     0,     0,
+     1,    10,     2,     8,     4,     5,     0,     9,    11,     0,
+     0,     0,     0,     0,     0,     0,     0,    21,    22,    23,
+    24,    12,    14,    26,    15,     0,     0,    16,    17,    20,
+     0,    18,    19,    13,     0,     0,     0
+};
+
+static const short yydefgoto[] = {    45,
+     5,     6,     7,    11,    12,    20,    32,    33
+};
+
+static const short yypact[] = {    18,
+-32768,    -1,     1,-32768,   -14,    18,   -11,     4,     5,    21,
+-32768,   -14,-32768,-32768,-32768,-32768,     9,-32768,-32768,     0,
+    10,    24,    25,    26,    27,    28,    29,-32768,-32768,-32768,
+-32768,-32768,    17,-32768,-32768,    33,    34,-32768,-32768,-32768,
+     0,-32768,-32768,-32768,    38,    39,-32768
+};
+
+static const short yypgoto[] = {-32768,
+    35,-32768,-32768,    30,-32768,-32768,     2,-32768
+};
+
+
+#define        YYLAST          43
+
+
+static const short yytable[] = {   -25,
+    21,     8,    10,     9,    14,    22,    23,    24,    25,    26,
+    27,    28,    29,    30,    31,   -25,   -25,    -3,     1,    15,
+    16,     2,     3,    17,    19,    34,    35,    36,    37,    38,
+    39,    40,    41,     4,    -3,    42,    43,    46,    47,     0,
+    13,    18,    44
+};
+
+static const short yycheck[] = {     0,
+     1,     3,    17,     3,    16,     6,     7,     8,     9,    10,
+    11,    12,    13,    14,    15,    16,    17,     0,     1,    16,
+    16,     4,     5,     3,    16,    16,     3,     3,     3,     3,
+     3,     3,    16,    16,    17,     3,     3,     0,     0,    -1,
+     6,    12,    41
+};
+/* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
+#line 3 "/usr/share/bison.simple"
+/* This file comes from bison-1.28.  */
+
+/* Skeleton output parser for bison,
+   Copyright (C) 1984, 1989, 1990 Free Software Foundation, 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, or (at your option)
+   any later version.
+
+   This program 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 this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, when this file is copied by Bison into a
+   Bison output file, you may use that output file without restriction.
+   This special exception was added by the Free Software Foundation
+   in version 1.24 of Bison.  */
+
+/* This is the parser code that is written into each bison parser
+  when the %semantic_parser declaration is not specified in the grammar.
+  It was written by Richard Stallman by simplifying the hairy parser
+  used when %semantic_parser is specified.  */
+
+#ifndef YYSTACK_USE_ALLOCA
+#ifdef alloca
+#define YYSTACK_USE_ALLOCA
+#else /* alloca not defined */
+#ifdef __GNUC__
+#define YYSTACK_USE_ALLOCA
+#define alloca __builtin_alloca
+#else /* not GNU C.  */
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386))
+#define YYSTACK_USE_ALLOCA
+#include <alloca.h>
+#else /* not sparc */
+/* We think this test detects Watcom and Microsoft C.  */
+/* This used to test MSDOS, but that is a bad idea
+   since that symbol is in the user namespace.  */
+#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__)
+#if 0 /* No need for malloc.h, which pollutes the namespace;
+        instead, just don't use alloca.  */
+#include <malloc.h>
+#endif
+#else /* not MSDOS, or __TURBOC__ */
+#if defined(_AIX)
+/* I don't know what this was needed for, but it pollutes the namespace.
+   So I turned it off.   rms, 2 May 1997.  */
+/* #include <malloc.h>  */
+ #pragma alloca
+#define YYSTACK_USE_ALLOCA
+#else /* not MSDOS, or __TURBOC__, or _AIX */
+#if 0
+#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up,
+                and on HPUX 10.  Eventually we can turn this on.  */
+#define YYSTACK_USE_ALLOCA
+#define alloca __builtin_alloca
+#endif /* __hpux */
+#endif
+#endif /* not _AIX */
+#endif /* not MSDOS, or __TURBOC__ */
+#endif /* not sparc */
+#endif /* not GNU C */
+#endif /* alloca not defined */
+#endif /* YYSTACK_USE_ALLOCA not defined */
+
+#ifdef YYSTACK_USE_ALLOCA
+#define YYSTACK_ALLOC alloca
+#else
+#define YYSTACK_ALLOC malloc
+#endif
+
+/* Note: there must be only one dollar sign in this file.
+   It is replaced by the list of actions, each action
+   as one case of the switch.  */
+
+#define yyerrok                (yyerrstatus = 0)
+#define yyclearin      (yychar = YYEMPTY)
+#define YYEMPTY                -2
+#define YYEOF          0
+#define YYACCEPT       goto yyacceptlab
+#define YYABORT        goto yyabortlab
+#define YYERROR                goto yyerrlab1
+/* Like YYERROR except do call yyerror.
+   This remains here temporarily to ease the
+   transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  */
+#define YYFAIL         goto yyerrlab
+#define YYRECOVERING()  (!!yyerrstatus)
+#define YYBACKUP(token, value) \
+do                                                             \
+  if (yychar == YYEMPTY && yylen == 1)                         \
+    { yychar = (token), yylval = (value);                      \
+      yychar1 = YYTRANSLATE (yychar);                          \
+      YYPOPSTACK;                                              \
+      goto yybackup;                                           \
+    }                                                          \
+  else                                                         \
+    { yyerror ("syntax error: cannot back up"); YYERROR; }     \
+while (0)
+
+#define YYTERROR       1
+#define YYERRCODE      256
+
+#ifndef YYPURE
+#define YYLEX          yylex()
+#endif
+
+#ifdef YYPURE
+#ifdef YYLSP_NEEDED
+#ifdef YYLEX_PARAM
+#define YYLEX          yylex(&yylval, &yylloc, YYLEX_PARAM)
+#else
+#define YYLEX          yylex(&yylval, &yylloc)
+#endif
+#else /* not YYLSP_NEEDED */
+#ifdef YYLEX_PARAM
+#define YYLEX          yylex(&yylval, YYLEX_PARAM)
+#else
+#define YYLEX          yylex(&yylval)
+#endif
+#endif /* not YYLSP_NEEDED */
+#endif
+
+/* If nonreentrant, generate the variables here */
+
+#ifndef YYPURE
+
+int    yychar;                 /*  the lookahead symbol                */
+YYSTYPE        yylval;                 /*  the semantic value of the           */
+                               /*  lookahead symbol                    */
+
+#ifdef YYLSP_NEEDED
+YYLTYPE yylloc;                        /*  location data for the lookahead     */
+                               /*  symbol                              */
+#endif
+
+int yynerrs;                   /*  number of parse errors so far       */
+#endif  /* not YYPURE */
+
+#if YYDEBUG != 0
+int yydebug;                   /*  nonzero means print parse trace     */
+/* Since this is uninitialized, it does not stop multiple parsers
+   from coexisting.  */
+#endif
+
+/*  YYINITDEPTH indicates the initial size of the parser's stacks      */
+
+#ifndef        YYINITDEPTH
+#define YYINITDEPTH 200
+#endif
+
+/*  YYMAXDEPTH is the maximum size the stacks can grow to
+    (effective only if the built-in stack extension method is used).  */
+
+#if YYMAXDEPTH == 0
+#undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+#define YYMAXDEPTH 10000
+#endif
+\f
+/* Define __yy_memcpy.  Note that the size argument
+   should be passed with type unsigned int, because that is what the non-GCC
+   definitions require.  With GCC, __builtin_memcpy takes an arg
+   of type size_t, but it can handle unsigned int.  */
+
+#if __GNUC__ > 1               /* GNU C and GNU C++ define this.  */
+#define __yy_memcpy(TO,FROM,COUNT)     __builtin_memcpy(TO,FROM,COUNT)
+#else                          /* not GNU C or C++ */
+#ifndef __cplusplus
+
+/* This is the most reliable way to avoid incompatibilities
+   in available built-in functions on various systems.  */
+static void
+__yy_memcpy (to, from, count)
+     char *to;
+     char *from;
+     unsigned int count;
+{
+  register char *f = from;
+  register char *t = to;
+  register int i = count;
+
+  while (i-- > 0)
+    *t++ = *f++;
+}
+
+#else /* __cplusplus */
+
+/* This is the most reliable way to avoid incompatibilities
+   in available built-in functions on various systems.  */
+static void
+__yy_memcpy (char *to, char *from, unsigned int count)
+{
+  register char *t = to;
+  register char *f = from;
+  register int i = count;
+
+  while (i-- > 0)
+    *t++ = *f++;
+}
+
+#endif
+#endif
+\f
+#line 217 "/usr/share/bison.simple"
+
+/* The user can define YYPARSE_PARAM as the name of an argument to be passed
+   into yyparse.  The argument should have type void *.
+   It should actually point to an object.
+   Grammar actions can access the variable by casting it
+   to the proper pointer type.  */
+
+#ifdef YYPARSE_PARAM
+#ifdef __cplusplus
+#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
+#define YYPARSE_PARAM_DECL
+#else /* not __cplusplus */
+#define YYPARSE_PARAM_ARG YYPARSE_PARAM
+#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
+#endif /* not __cplusplus */
+#else /* not YYPARSE_PARAM */
+#define YYPARSE_PARAM_ARG
+#define YYPARSE_PARAM_DECL
+#endif /* not YYPARSE_PARAM */
+
+/* Prevent warning if -Wstrict-prototypes.  */
+#ifdef __GNUC__
+#ifdef YYPARSE_PARAM
+int yyparse (void *);
+#else
+int yyparse (void);
+#endif
+#endif
+
+int
+yyparse(YYPARSE_PARAM_ARG)
+     YYPARSE_PARAM_DECL
+{
+  register int yystate;
+  register int yyn;
+  register short *yyssp;
+  register YYSTYPE *yyvsp;
+  int yyerrstatus;     /*  number of tokens to shift before error messages enabled */
+  int yychar1 = 0;             /*  lookahead token as an internal (translated) token number */
+
+  short        yyssa[YYINITDEPTH];     /*  the state stack                     */
+  YYSTYPE yyvsa[YYINITDEPTH];  /*  the semantic value stack            */
+
+  short *yyss = yyssa;         /*  refer to the stacks thru separate pointers */
+  YYSTYPE *yyvs = yyvsa;       /*  to allow yyoverflow to reallocate them elsewhere */
+
+#ifdef YYLSP_NEEDED
+  YYLTYPE yylsa[YYINITDEPTH];  /*  the location stack                  */
+  YYLTYPE *yyls = yylsa;
+  YYLTYPE *yylsp;
+
+#define YYPOPSTACK   (yyvsp--, yyssp--, yylsp--)
+#else
+#define YYPOPSTACK   (yyvsp--, yyssp--)
+#endif
+
+  int yystacksize = YYINITDEPTH;
+  int yyfree_stacks = 0;
+
+#ifdef YYPURE
+  int yychar;
+  YYSTYPE yylval;
+  int yynerrs;
+#ifdef YYLSP_NEEDED
+  YYLTYPE yylloc;
+#endif
+#endif
+
+  YYSTYPE yyval;               /*  the variable used to return         */
+                               /*  semantic values from the action     */
+                               /*  routines                            */
+
+  int yylen;
+
+#if YYDEBUG != 0
+  if (yydebug)
+    fprintf(stderr, "Starting parse\n");
+#endif
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY;            /* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+
+  yyssp = yyss - 1;
+  yyvsp = yyvs;
+#ifdef YYLSP_NEEDED
+  yylsp = yyls;
+#endif
+
+/* Push a new state, which is found in  yystate  .  */
+/* In all cases, when you get here, the value and location stacks
+   have just been pushed. so pushing a state here evens the stacks.  */
+yynewstate:
+
+  *++yyssp = yystate;
+
+  if (yyssp >= yyss + yystacksize - 1)
+    {
+      /* Give user a chance to reallocate the stack */
+      /* Use copies of these so that the &'s don't force the real ones into memory. */
+      YYSTYPE *yyvs1 = yyvs;
+      short *yyss1 = yyss;
+#ifdef YYLSP_NEEDED
+      YYLTYPE *yyls1 = yyls;
+#endif
+
+      /* Get the current used size of the three stacks, in elements.  */
+      int size = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      /* Each stack pointer address is followed by the size of
+        the data in use in that stack, in bytes.  */
+#ifdef YYLSP_NEEDED
+      /* This used to be a conditional around just the two extra args,
+        but that might be undefined if yyoverflow is a macro.  */
+      yyoverflow("parser stack overflow",
+                &yyss1, size * sizeof (*yyssp),
+                &yyvs1, size * sizeof (*yyvsp),
+                &yyls1, size * sizeof (*yylsp),
+                &yystacksize);
+#else
+      yyoverflow("parser stack overflow",
+                &yyss1, size * sizeof (*yyssp),
+                &yyvs1, size * sizeof (*yyvsp),
+                &yystacksize);
+#endif
+
+      yyss = yyss1; yyvs = yyvs1;
+#ifdef YYLSP_NEEDED
+      yyls = yyls1;
+#endif
+#else /* no yyoverflow */
+      /* Extend the stack our own way.  */
+      if (yystacksize >= YYMAXDEPTH)
+       {
+         yyerror("parser stack overflow");
+         if (yyfree_stacks)
+           {
+             free (yyss);
+             free (yyvs);
+#ifdef YYLSP_NEEDED
+             free (yyls);
+#endif
+           }
+         return 2;
+       }
+      yystacksize *= 2;
+      if (yystacksize > YYMAXDEPTH)
+       yystacksize = YYMAXDEPTH;
+#ifndef YYSTACK_USE_ALLOCA
+      yyfree_stacks = 1;
+#endif
+      yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp));
+      __yy_memcpy ((char *)yyss, (char *)yyss1,
+                  size * (unsigned int) sizeof (*yyssp));
+      yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp));
+      __yy_memcpy ((char *)yyvs, (char *)yyvs1,
+                  size * (unsigned int) sizeof (*yyvsp));
+#ifdef YYLSP_NEEDED
+      yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp));
+      __yy_memcpy ((char *)yyls, (char *)yyls1,
+                  size * (unsigned int) sizeof (*yylsp));
+#endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + size - 1;
+      yyvsp = yyvs + size - 1;
+#ifdef YYLSP_NEEDED
+      yylsp = yyls + size - 1;
+#endif
+
+#if YYDEBUG != 0
+      if (yydebug)
+       fprintf(stderr, "Stack size increased to %d\n", yystacksize);
+#endif
+
+      if (yyssp >= yyss + yystacksize - 1)
+       YYABORT;
+    }
+
+#if YYDEBUG != 0
+  if (yydebug)
+    fprintf(stderr, "Entering state %d\n", yystate);
+#endif
+
+  goto yybackup;
+ yybackup:
+
+/* Do appropriate processing given the current state.  */
+/* Read a lookahead token if we need one and don't already have one.  */
+/* yyresume: */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* yychar is either YYEMPTY or YYEOF
+     or a valid token in external form.  */
+
+  if (yychar == YYEMPTY)
+    {
+#if YYDEBUG != 0
+      if (yydebug)
+       fprintf(stderr, "Reading a token: ");
+#endif
+      yychar = YYLEX;
+    }
+
+  /* Convert token to internal form (in yychar1) for indexing tables with */
+
+  if (yychar <= 0)             /* This means end of input. */
+    {
+      yychar1 = 0;
+      yychar = YYEOF;          /* Don't call YYLEX any more */
+
+#if YYDEBUG != 0
+      if (yydebug)
+       fprintf(stderr, "Now at end of input.\n");
+#endif
+    }
+  else
+    {
+      yychar1 = YYTRANSLATE(yychar);
+
+#if YYDEBUG != 0
+      if (yydebug)
+       {
+         fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
+         /* Give the individual parser a way to print the precise meaning
+            of a token, for further debugging info.  */
+#ifdef YYPRINT
+         YYPRINT (stderr, yychar, yylval);
+#endif
+         fprintf (stderr, ")\n");
+       }
+#endif
+    }
+
+  yyn += yychar1;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
+    goto yydefault;
+
+  yyn = yytable[yyn];
+
+  /* yyn is what to do for this token type in this state.
+     Negative => reduce, -yyn is rule number.
+     Positive => shift, yyn is new state.
+       New state is final state => don't bother to shift,
+       just return success.
+     0, or most negative number => error.  */
+
+  if (yyn < 0)
+    {
+      if (yyn == YYFLAG)
+       goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrlab;
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  /* Shift the lookahead token.  */
+
+#if YYDEBUG != 0
+  if (yydebug)
+    fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
+#endif
+
+  /* Discard the token being shifted unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
+
+  *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+  *++yylsp = yylloc;
+#endif
+
+  /* count tokens shifted since error; after three, turn off error status.  */
+  if (yyerrstatus) yyerrstatus--;
+
+  yystate = yyn;
+  goto yynewstate;
+
+/* Do the default action for the current state.  */
+yydefault:
+
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+
+/* Do a reduction.  yyn is the number of a rule to reduce with.  */
+yyreduce:
+  yylen = yyr2[yyn];
+  if (yylen > 0)
+    yyval = yyvsp[1-yylen]; /* implement default value of the action */
+
+#if YYDEBUG != 0
+  if (yydebug)
+    {
+      int i;
+
+      fprintf (stderr, "Reducing via rule %d (line %d), ",
+              yyn, yyrline[yyn]);
+
+      /* Print the symbols being reduced, and their result.  */
+      for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
+       fprintf (stderr, "%s ", yytname[yyrhs[i]]);
+      fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
+    }
+#endif
+
+
+  switch (yyn) {
+
+case 4:
+#line 59 "/windows/build/xemacs/xemacs/netinstall/iniparse.y"
+{ setup_timestamp = strtoul (yyvsp[-1], 0, 0); ;
+    break;}
+case 5:
+#line 60 "/windows/build/xemacs/xemacs/netinstall/iniparse.y"
+{ setup_version = strdup (yyvsp[-1]); ;
+    break;}
+case 7:
+#line 62 "/windows/build/xemacs/xemacs/netinstall/iniparse.y"
+{ yyerror ("unrecognized line in setup.ini headers (do you have the latest setup?)"); ;
+    break;}
+case 11:
+#line 71 "/windows/build/xemacs/xemacs/netinstall/iniparse.y"
+{ new_package(yyvsp[-1]); ;
+    break;}
+case 15:
+#line 81 "/windows/build/xemacs/xemacs/netinstall/iniparse.y"
+{ cpt->version = yyvsp[0]; ;
+    break;}
+case 16:
+#line 82 "/windows/build/xemacs/xemacs/netinstall/iniparse.y"
+{ cp->sdesc = yyvsp[0]; ;
+    break;}
+case 17:
+#line 83 "/windows/build/xemacs/xemacs/netinstall/iniparse.y"
+{ cp->ldesc = yyvsp[0]; ;
+    break;}
+case 18:
+#line 84 "/windows/build/xemacs/xemacs/netinstall/iniparse.y"
+{ cpt->install = yyvsp[-1];
+                                 cpt->install_size = atoi(yyvsp[0]); ;
+    break;}
+case 19:
+#line 86 "/windows/build/xemacs/xemacs/netinstall/iniparse.y"
+{ cpt->source = yyvsp[-1];
+                                 cpt->source_size = atoi(yyvsp[0]); ;
+    break;}
+case 20:
+#line 88 "/windows/build/xemacs/xemacs/netinstall/iniparse.y"
+{ if (!strcmp (yyvsp[0], "cygwin"))
+                                       cp->type = TY_CYGWIN;
+                                 else if (!strcmp (yyvsp[0], "native"))
+                                       cp->type = TY_NATIVE;
+                                 else 
+                                       cp->type = TY_GENERIC; ;
+    break;}
+case 21:
+#line 94 "/windows/build/xemacs/xemacs/netinstall/iniparse.y"
+{ trust = TRUST_PREV; ;
+    break;}
+case 22:
+#line 95 "/windows/build/xemacs/xemacs/netinstall/iniparse.y"
+{ trust = TRUST_CURR; ;
+    break;}
+case 23:
+#line 96 "/windows/build/xemacs/xemacs/netinstall/iniparse.y"
+{ trust = TRUST_TEST; ;
+    break;}
+case 24:
+#line 97 "/windows/build/xemacs/xemacs/netinstall/iniparse.y"
+{ trust = TRUST_UNKNOWN; ;
+    break;}
+case 26:
+#line 99 "/windows/build/xemacs/xemacs/netinstall/iniparse.y"
+{ yylineno --;
+               yyerror ("unrecognized line in package %s (do you have the latest setup?)", cp->name);
+               yylineno ++;
+             ;
+    break;}
+}
+   /* the action file gets copied in in place of this dollarsign */
+#line 543 "/usr/share/bison.simple"
+\f
+  yyvsp -= yylen;
+  yyssp -= yylen;
+#ifdef YYLSP_NEEDED
+  yylsp -= yylen;
+#endif
+
+#if YYDEBUG != 0
+  if (yydebug)
+    {
+      short *ssp1 = yyss - 1;
+      fprintf (stderr, "state stack now");
+      while (ssp1 != yyssp)
+       fprintf (stderr, " %d", *++ssp1);
+      fprintf (stderr, "\n");
+    }
+#endif
+
+  *++yyvsp = yyval;
+
+#ifdef YYLSP_NEEDED
+  yylsp++;
+  if (yylen == 0)
+    {
+      yylsp->first_line = yylloc.first_line;
+      yylsp->first_column = yylloc.first_column;
+      yylsp->last_line = (yylsp-1)->last_line;
+      yylsp->last_column = (yylsp-1)->last_column;
+      yylsp->text = 0;
+    }
+  else
+    {
+      yylsp->last_line = (yylsp+yylen-1)->last_line;
+      yylsp->last_column = (yylsp+yylen-1)->last_column;
+    }
+#endif
+
+  /* Now "shift" the result of the reduction.
+     Determine what state that goes to,
+     based on the state we popped back to
+     and the rule number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
+  if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTBASE];
+
+  goto yynewstate;
+
+yyerrlab:   /* here on detecting error */
+
+  if (! yyerrstatus)
+    /* If not already recovering from an error, report this error.  */
+    {
+      ++yynerrs;
+
+#ifdef YYERROR_VERBOSE
+      yyn = yypact[yystate];
+
+      if (yyn > YYFLAG && yyn < YYLAST)
+       {
+         int size = 0;
+         char *msg;
+         int x, count;
+
+         count = 0;
+         /* Start X at -yyn if nec to avoid negative indexes in yycheck.  */
+         for (x = (yyn < 0 ? -yyn : 0);
+              x < (sizeof(yytname) / sizeof(char *)); x++)
+           if (yycheck[x + yyn] == x)
+             size += strlen(yytname[x]) + 15, count++;
+         msg = (char *) malloc(size + 15);
+         if (msg != 0)
+           {
+             strcpy(msg, "parse error");
+
+             if (count < 5)
+               {
+                 count = 0;
+                 for (x = (yyn < 0 ? -yyn : 0);
+                      x < (sizeof(yytname) / sizeof(char *)); x++)
+                   if (yycheck[x + yyn] == x)
+                     {
+                       strcat(msg, count == 0 ? ", expecting `" : " or `");
+                       strcat(msg, yytname[x]);
+                       strcat(msg, "'");
+                       count++;
+                     }
+               }
+             yyerror(msg);
+             free(msg);
+           }
+         else
+           yyerror ("parse error; also virtual memory exceeded");
+       }
+      else
+#endif /* YYERROR_VERBOSE */
+       yyerror("parse error");
+    }
+
+  goto yyerrlab1;
+yyerrlab1:   /* here on error raised explicitly by an action */
+
+  if (yyerrstatus == 3)
+    {
+      /* if just tried and failed to reuse lookahead token after an error, discard it.  */
+
+      /* return failure if at end of input */
+      if (yychar == YYEOF)
+       YYABORT;
+
+#if YYDEBUG != 0
+      if (yydebug)
+       fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
+#endif
+
+      yychar = YYEMPTY;
+    }
+
+  /* Else will try to reuse lookahead token
+     after shifting the error token.  */
+
+  yyerrstatus = 3;             /* Each real token shifted decrements this */
+
+  goto yyerrhandle;
+
+yyerrdefault:  /* current state does not do anything special for the error token. */
+
+#if 0
+  /* This is wrong; only states that explicitly want error tokens
+     should shift them.  */
+  yyn = yydefact[yystate];  /* If its default is to accept any token, ok.  Otherwise pop it.*/
+  if (yyn) goto yydefault;
+#endif
+
+yyerrpop:   /* pop the current state because it cannot handle the error token */
+
+  if (yyssp == yyss) YYABORT;
+  yyvsp--;
+  yystate = *--yyssp;
+#ifdef YYLSP_NEEDED
+  yylsp--;
+#endif
+
+#if YYDEBUG != 0
+  if (yydebug)
+    {
+      short *ssp1 = yyss - 1;
+      fprintf (stderr, "Error: state stack now");
+      while (ssp1 != yyssp)
+       fprintf (stderr, " %d", *++ssp1);
+      fprintf (stderr, "\n");
+    }
+#endif
+
+yyerrhandle:
+
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yyerrdefault;
+
+  yyn += YYTERROR;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
+    goto yyerrdefault;
+
+  yyn = yytable[yyn];
+  if (yyn < 0)
+    {
+      if (yyn == YYFLAG)
+       goto yyerrpop;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrpop;
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+#if YYDEBUG != 0
+  if (yydebug)
+    fprintf(stderr, "Shifting error token, ");
+#endif
+
+  *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+  *++yylsp = yylloc;
+#endif
+
+  yystate = yyn;
+  goto yynewstate;
+
+ yyacceptlab:
+  /* YYACCEPT comes here.  */
+  if (yyfree_stacks)
+    {
+      free (yyss);
+      free (yyvs);
+#ifdef YYLSP_NEEDED
+      free (yyls);
+#endif
+    }
+  return 0;
+
+ yyabortlab:
+  /* YYABORT comes here.  */
+  if (yyfree_stacks)
+    {
+      free (yyss);
+      free (yyvs);
+#ifdef YYLSP_NEEDED
+      free (yyls);
+#endif
+    }
+  return 1;
+}
+#line 105 "/windows/build/xemacs/xemacs/netinstall/iniparse.y"
+
+
+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/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)))