From 23c9e63cf98957abe63d005768701c83cf7cf9f2 Mon Sep 17 00:00:00 2001 From: DJ Delorie Date: Fri, 7 Jul 2000 00:29:21 +0000 Subject: [PATCH] * Replace everything with a new GUI version * zlib/gzio.c: add gzctell() for progress displays --- ChangeLog | 9 + Makefile.in | 152 +-- README | 32 +- choose.cc | 100 ++ concat.cc | 77 ++ concat.h | 21 + ctar.c | 54 -- cygcalls.c | 107 --- dialog.cc | 94 ++ dialog.h | 64 ++ diskfull.cc | 67 ++ diskfull.h | 17 + download.cc | 80 ++ error.c | 51 - find.cc | 73 ++ find.h | 22 + fromcwd.cc | 147 +++ geturl.cc | 251 +++++ geturl.h | 21 + gzip.exe.gz | Bin 23849 -> 0 bytes ini.cc | 108 +++ ini.h | 64 ++ inilex.l | 90 ++ iniparse.y | 107 +++ install.cc | 313 +++++++ main.cc | 75 ++ memory.c | 49 - mkdir.cc | 79 ++ strarry.h => mkdir.h | 19 +- mount.cc | 129 +++ mount.h | 25 + msg.cc | 68 ++ msg.h | 33 + net.cc | 152 +++ netio.cc | 128 +++ netio.h | 45 + nio-file.cc | 64 ++ cygcalls.h => nio-file.h | 15 +- nio-ie5.cc | 92 ++ nio-ie5.h | 25 + other.cc | 97 ++ path.c | 160 ---- pkg.c | 305 ------ port.h | 28 + res.rc | 272 ++++++ resource.h | 73 +- root.cc | 214 +++++ setup.c | 1910 -------------------------------------- setup.dsp | 130 --- setup.dsw | 44 - setup.h | 54 -- setupres.rc | 5 - site.cc | 190 ++++ source.cc | 111 +++ state.cc | 19 + state.h | 37 + strarry.c | 45 - tar.c => tar.cc | 89 +- tar.exe.gz | Bin 54468 -> 0 bytes tar.h | 5 + win32.h | 33 + xsystem.c | 83 -- zlib.dsp | 192 ---- zlib/gzio.c | 16 + zlib/zlib.h | 5 + 65 files changed, 3881 insertions(+), 3355 deletions(-) create mode 100644 choose.cc create mode 100644 concat.cc create mode 100644 concat.h delete mode 100644 ctar.c delete mode 100644 cygcalls.c create mode 100644 dialog.cc create mode 100644 dialog.h create mode 100644 diskfull.cc create mode 100644 diskfull.h create mode 100644 download.cc delete mode 100644 error.c create mode 100644 find.cc create mode 100644 find.h create mode 100644 fromcwd.cc create mode 100644 geturl.cc create mode 100644 geturl.h delete mode 100755 gzip.exe.gz create mode 100644 ini.cc create mode 100644 ini.h create mode 100644 inilex.l create mode 100644 iniparse.y create mode 100644 install.cc create mode 100644 main.cc delete mode 100644 memory.c create mode 100644 mkdir.cc rename strarry.h => mkdir.h (53%) create mode 100644 mount.cc create mode 100644 mount.h create mode 100644 msg.cc create mode 100644 msg.h create mode 100644 net.cc create mode 100644 netio.cc create mode 100644 netio.h create mode 100644 nio-file.cc rename cygcalls.h => nio-file.h (70%) create mode 100644 nio-ie5.cc create mode 100644 nio-ie5.h create mode 100644 other.cc delete mode 100644 path.c delete mode 100644 pkg.c create mode 100644 port.h create mode 100644 res.rc create mode 100644 root.cc delete mode 100644 setup.c delete mode 100644 setup.dsp delete mode 100644 setup.dsw delete mode 100644 setup.h delete mode 100644 setupres.rc create mode 100644 site.cc create mode 100644 source.cc create mode 100644 state.cc create mode 100644 state.h delete mode 100644 strarry.c rename tar.c => tar.cc (89%) delete mode 100755 tar.exe.gz create mode 100644 win32.h delete mode 100644 xsystem.c delete mode 100644 zlib.dsp diff --git a/ChangeLog b/ChangeLog index d92f196d..da74a9e6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2000-07-06 DJ Delorie + + * Replace everything with a new GUI version + * zlib/gzio.c: add gzctell() for progress displays + +2000-06-22 DJ Delorie + + * setup.c (tarx): re-add call to write_pkg() + 2000-06-07 DJ Delorie * cygcalls.c: new, call cygwin1.dll functions directly diff --git a/Makefile.in b/Makefile.in index 18db4e6d..d1604f1a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -12,90 +12,112 @@ # # Makefile for Cygwin installer -SHELL:=@SHELL@ +SHELL := @SHELL@ -srcdir:=@srcdir@ -VPATH:=@srcdir@ -prefix:=@prefix@ -exec_prefix:=@exec_prefix@ +srcdir := @srcdir@ +VPATH := @srcdir@ +prefix := @prefix@ +exec_prefix := @exec_prefix@ -bindir:=@bindir@ -etcdir:=$(exec_prefix)/etc -program_transform_name:=@program_transform_name@ +bindir := @bindir@ +etcdir := $(exec_prefix)/etc -INSTALL:=@INSTALL@ -INSTALL_PROGRAM:=@INSTALL_PROGRAM@ -INSTALL_DATA:=@INSTALL_DATA@ +program_transform_name := @program_transform_name@ -EXEEXT:=@EXEEXT@ -EXEEXT_FOR_BUILD:=@EXEEXT_FOR_BUILD@ +INSTALL := @INSTALL@ +INSTALL_PROGRAM := @INSTALL_PROGRAM@ +INSTALL_DATA := @INSTALL_DATA@ -CC:=@CC@ -CC_FOR_TARGET:=$(CC) +EXEEXT := @EXEEXT@ +EXEEXT_FOR_BUILD := @EXEEXT_FOR_BUILD@ -CFLAGS:=@CFLAGS@ -nostdinc -CXXFLAGS:=@CXXFLAGS@ -fno-exceptions -nostdinc++ -fno-rtti +CC := @CC@ +CC_FOR_TARGET := $(CC) -WINDRES:=@WINDRES@ -OBJCOPY:=@OBJCOPY@ +CFLAGS := @CFLAGS@ -nostdinc +CXXFLAGS := @CXXFLAGS@ -fno-exceptions -nostdinc++ -fno-rtti + +WINDRES := @WINDRES@ +OBJCOPY := @OBJCOPY@ include $(srcdir)/../Makefile.common -MINGW_INCLUDES:=-I$(mingw_source)/include -I$(w32api_include) +MINGW_INCLUDES := -I. -I$(mingw_source)/include -I$(w32api_include) + +MINGW_CXXFLAGS := $(CXXFLAGS) -mno-cygwin $(MINGW_INCLUDES) -mwindows +MINGW_CFLAGS := $(CFLAGS) -mno-cygwin $(MINGW_INCLUDES) -mwindows -MINGW_CXXFLAGS:=$(CXXFLAGS) -mno-cygwin $(MINGW_INCLUDES) -MINGW_CFLAGS:=$(CFLAGS) -mno-cygwin $(MINGW_INCLUDES) +ZLIB := zlib/libzcygw.a +libmingw32.a := $(mingw_build)/libmingw32.a +libuser32 := $(w32api_lib)/libuser32.a +libkernel32 := $(w32api_lib)/libkernel32.a -ZLIB=zlib/libzcygw.a -libmingw32.a:=$(mingw_build)/libmingw32.a -libuser32:=$(w32api_lib)/libuser32.a -libkernel32:=$(w32api_lib)/libkernel32.a -ALL_DEP_LDLIBS:=$(ZLIB) $(w32api_lib)/libole32.a $(w32api_lib)/libwininet.a \ +ALL_DEP_LDLIBS := $(ZLIB) $(w32api_lib)/libole32.a $(w32api_lib)/libwininet.a \ $(w32api_lib)/libnetapi32.a $(w32api_lib)/libadvapi32.a \ $(w32api_lib)/libuuid.a $(libkernel32) $(w32api_lib)/libuser32.a \ $(libmingw32) -ALL_LDLIBS:=${patsubst $(mingw_build)/lib%.a,-l%,\ +ALL_LDLIBS := ${patsubst $(mingw_build)/lib%.a,-l%,\ ${patsubst $(w32api_lib)/lib%.a,-l%,\ ${filter-out $(libmingw32),\ ${filter-out $(libuser32),\ ${filter-out $(libkernel32), $(ALL_DEP_LDLIBS)}}}}} -ALL_LDFLAGS:=${filter-out -I%, \ +ALL_LDFLAGS := ${filter-out -I%, \ ${filter-out -W%, \ -B$(w32api_lib)/ -B${mingw_build}/ $(MINGW_CFLAGS) $(LDFLAGS)}} -PROGS:=setup$(EXEEXT) - -OBJS:=cygcalls.o error.o memory.o setup.o strarry.o cinstall.o path.o pkg.o tar.o xsystem.o +PROGS := setup$(EXEEXT) + +OBJS = \ + choose.o \ + concat.o \ + dialog.o \ + diskfull.o \ + download.o \ + find.o \ + fromcwd.o \ + geturl.o \ + ini.o \ + inilex.o \ + iniparse.o \ + install.o \ + main.o \ + mkdir.o \ + mount.o \ + msg.o \ + net.o \ + netio.o \ + nio-ie5.o \ + nio-file.o \ + other.o \ + res.o \ + root.o \ + site.o \ + source.o \ + state.o \ + tar.o \ + $E -BUNDLED_FILES:=cygwin1.dll.gz -# mount.exe.gz cygpath.exe.gz umount.exe.gz .SUFFIXES: .NOEXPORT: .PHONY: all install clean realclean -.PRECIOUS: $(utils_build)/cygpath.exe $(utils_build)/mount.exe $(utils_build)/umount.exe $(cygwin_build)/new-cygwin1.dll all: Makefile $(PROGS) setup$(EXEEXT): $(OBJS) $(ALL_DEP_LDLIBS) ifdef VERBOSE - $(CC) -o $@ ${filter-out $(ALL_DEP_LIBS),$^} + $(CC) $(MINGW_CXXFLAGS) -o $@ ${filter-out $(ALL_DEP_LIBS),$^} else @echo $(CC) ... -o $@ $(OBJS) - @$(CC) -o $@ ${filter-out $(ALL_DEP_LIBS),$^} $(ALL_LDFLAGS) $(ALL_LDLIBS) + @$(CC) $(MINGW_CXXFLAGS) -o $@ ${filter-out $(ALL_DEP_LIBS),$^} $(ALL_LDFLAGS) $(ALL_LDLIBS) endif @chmod a-x $@ -ctar.exe : ctar.o tar.o $(ALL_DEP_LDLIBS) - $(CC) -o $@ ctar.o tar.o $(ALL_LDFLAGS) $(ALL_LDLIBS) - -mingw_getopt.o: $(cygwin_source)/getopt.c - $(CC) -c -o $@ $(MINGW_CFLAGS) $^ - clean: - rm -f *.o *.rc $(PROGS) zlib/*.o zlib/*.a *.exe *.gz + rm -f *.o *.rc $(PROGS) + $(MAKE) -C zlib clean realclean: clean rm -f Makefile config.cache @@ -111,33 +133,10 @@ $(libmingw32): $(mingw_build)/Makefile @$(MAKE) -C $(@D) $(@F) $(ZLIB): zlib/Makefile - $(MAKE) -C $(@D) $(@F) CFLAGS='$(MINGW_CFLAGS)' - -%.exe.gz: %.exe - gzip -9nf $? - -%.exe: $(utils_build)/%.exe - $(OBJCOPY) --strip-unneeded $? $@ - -$(utils_build)/%.exe: $(utils_build)/Makefile - @$(MAKE) -C $(utils_build) $(@F) - -%.dll.gz: new-%.dll - gzip -9nfc $? > $@ - -%.dll: $(cygwin_build)/%.dll - $(OBJCOPY) --strip-unneeded $? $@ - -$(cygwin_build)/%.dll: $(cygwin_build)/Makefile - @$(MAKE) -C $(@D) $(@F) - -cinstall.rc: $(BUNDLED_FILES) $(srcdir)/Makefile.in - for f in $(BUNDLED_FILES); do \ - echo `basename $$f .gz` FILE DISCARDABLE '"'$$f'"'; \ - done > $@ + $(MAKE) -C $(@D) $(@F) CC="$(CC)" CFLAGS='$(MINGW_CFLAGS)' %.o: %.rc - $(WINDRES) -o $@ $? + $(WINDRES) --include-dir $(srcdir) -o $@ $? %.o: %.c ifdef VERBOSE @@ -146,3 +145,18 @@ else @echo $(CC) -c $(CFLAGS) ... $(?F) @$(CC) $(MINGW_CFLAGS) -c -o $@ $? endif + +%.o: %.cc +ifdef VERBOSE + $(CC) $(MINGW_CXXFLAGS) -c -o $@ $? +else + @echo $(CC) -c $(CXXFLAGS) ... $(?F) + @$(CC) $(MINGW_CXXFLAGS) -c -o $@ $? +endif + +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 diff --git a/README b/README index fa76ca85..7a13a1e4 100644 --- a/README +++ b/README @@ -1,6 +1,32 @@ This directory contains the source for the setup program for the cygwin net releases. -If you have any problems the initial version of this program was -written by Ron Parker. Currently, March 2000, he may be reached at -rdparker@butlermfg.com. + + +To-Do list: + +-- mandatory -- + +cygwin.bat + +install icon + +-- future -- + +install.cc: read old .lst.gz file before overwriting it; remove any +files in the old install that aren't also in the new install. + +add netio subclasses for direct HTTP, FTP and proxy connections + +change nio-ie5 to auto-load the wininet DLL + +choose.cc: add a dialog to let user choose what to install and +which versions to install + +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. + +main.cc: add splash screen and copyright notice diff --git a/choose.cc b/choose.cc new file mode 100644 index 00000000..b5a924c0 --- /dev/null +++ b/choose.cc @@ -0,0 +1,100 @@ +/* + * 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 + * + */ + +/* 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 +#include "dialog.h" +#include "resource.h" +#include "state.h" +#include "ini.h" +#include "concat.h" +#include "msg.h" + +void +do_choose (HINSTANCE h) +{ + int trust_prefs[NTRUST]; + int i, t; + + /* support this later */ + trust_level = TRUST_CURR; + + t = 0; + for (i=trust_level; i>=0; i--) + trust_prefs[t++] = i; + for (i=trust_level+1; i + * + */ + +/* See concat.h. Note that we canonicalize the result, this avoids + multiple slashes being interpreted as UNCs. */ + +#include +#include +#include + +char * +concat (char *s, ...) +{ + int len = strlen(s); + char *rv, *arg; + va_list v; + + if (!s) + return 0; + + 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] == '/') + { + *d++ = *++s; + *d++ = *++s; + } + else if (*s == '/') + while (s[1] == '/') + s++; + } + *d = 0; + + return rv; +} diff --git a/concat.h b/concat.h new file mode 100644 index 00000000..134f48c4 --- /dev/null +++ b/concat.h @@ -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 + * + */ + +/* 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 * concat (char *s, ...); diff --git a/ctar.c b/ctar.c deleted file mode 100644 index b17ff4e4..00000000 --- a/ctar.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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 - * - */ - -#include -#include "tar.h" - -extern int _tar_verbose; - -int -main (int argc, char **argv) -{ - char **map = (char **) malloc ((argc+2) * sizeof (char *)); - int i, j; - - while (argc > 1 && strcmp (argv[1], "-v") == 0) - { - _tar_verbose ++; - argc--; - argv++; - } - - if (argc < 2) - { - fprintf (stderr, "Usage: ctar [from to [from to ...]]\n"); - exit (1); - } - - j = 0; - for (i = 2; i < argc; i ++) - map[j++] = argv[i]; - map[j++] = 0; - map[j++] = 0; - - i = tar_auto (argv[1], map); - - if (i == 1) - fprintf (stderr, "ctar: there was an error extracting %s\n", argv[1]); - else if (i > 1) - fprintf (stderr, "ctar: there were errors extracting %s\n", argv[1]); - - return i; -} diff --git a/cygcalls.c b/cygcalls.c deleted file mode 100644 index 03dba451..00000000 --- a/cygcalls.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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 - * - */ - -#include -#include - -static HINSTANCE cygwin_dll = 0; -static char *cygwin_dll_name = 0; - -static void (*cygwin_dll_init_proc) (); -static int (*mount_proc) (const char *win32_path, const char *posix_path, unsigned flags); -static int (*umount_proc) (const char *posix_path); -static int (*cygwin_umount_proc) (const char *posix_path, unsigned flags); -static FILE * (*setmntent_proc) (const char *, const char *); -static struct mntent * (*getmntent_proc) (FILE *); -static int (*endmntent_proc) (FILE *); - -static void -one (void *fp, char *name) -{ - int a; - *(int *)fp = a = (int) GetProcAddress (cygwin_dll, name); - if (!a) - { - fprintf (stderr, "error: unable to find `%s' in %s\n", name, cygwin_dll_name); - exit (1); - } -} - -int -cygcall_load_dll (char *name) -{ - /* This forces the dll to use a private "shared" area, avoiding version conflicts */ - SetEnvironmentVariable("CYGWIN_TESTING", "1"); - - cygwin_dll = LoadLibrary (name); - if (cygwin_dll == 0) - return 1; - cygwin_dll_name = name; - - one (&cygwin_dll_init_proc, "cygwin_dll_init"); - one (&mount_proc, "mount"); - one (&umount_proc, "umount"); - one (&cygwin_umount_proc, "cygwin_umount"); - one (&setmntent_proc, "setmntent"); - one (&getmntent_proc, "getmntent"); - one (&endmntent_proc, "endmntent"); - - cygwin_dll_init_proc (); - - return 0; -} - -int -cygcall_unload_dll () -{ - FreeLibrary (cygwin_dll); -} - -int -mount (const char *win32_path, const char *posix_path, unsigned flags) -{ - return mount_proc (win32_path, posix_path, flags); -} - -int -umount (const char *posix_path) -{ - return umount_proc (posix_path); -} - -int -cygwin_umount (const char *posix_path, unsigned flags) -{ - return cygwin_umount_proc (posix_path, flags); -} - -FILE * -setmntent (const char *__filep, const char *__type) -{ - return setmntent_proc (__filep, __type); -} - -struct mntent * -getmntent (FILE *__filep) -{ - return getmntent_proc (__filep); -} - -int -endmntent (FILE *__filep) -{ - return endmntent_proc (__filep); -} - diff --git a/dialog.cc b/dialog.cc new file mode 100644 index 00000000..dba17758 --- /dev/null +++ b/dialog.cc @@ -0,0 +1,94 @@ +/* + * 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 + * + */ + +/* The purpose of this file is to provide common functionality for + all the dialogs in the program. */ + +#include "win32.h" +#include +#include +#include "dialog.h" +#include "msg.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 *msg) +{ + DWORD e = GetLastError(); + char *buf; + FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + 0, + e, + 0, + (CHAR *)&buf, + 0, + 0); + MessageBox (0, buf, msg, 0); + ExitProcess (0); +} diff --git a/dialog.h b/dialog.h new file mode 100644 index 00000000..4d185e04 --- /dev/null +++ b/dialog.h @@ -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 + * + */ + +/* 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; + +#define D(x) void x(HINSTANCE _h) + +/* prototypes for all the do_* functions called by main.cc */ +D(do_source); +D(do_root); +D(do_net); +D(do_site); +D(do_other); +D(do_choose); +D(do_ini); +D(do_fromcwd); +D(do_download); +D(do_install); + +#undef D + +/* end this dialog and select the next. Pass 0 to exit the program */ +#define NEXT(id) EndDialog(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/diskfull.cc b/diskfull.cc new file mode 100644 index 00000000..10bd67c9 --- /dev/null +++ b/diskfull.cc @@ -0,0 +1,67 @@ +/* + * 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 + * + */ + +/* 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) +{ + WINAPI 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/diskfull.h b/diskfull.h new file mode 100644 index 00000000..e198a748 --- /dev/null +++ b/diskfull.h @@ -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 + * + */ + +/* returns 0..100 (percent) */ +int diskfull (char *path); diff --git a/download.cc b/download.cc new file mode 100644 index 00000000..a4d67fc3 --- /dev/null +++ b/download.cc @@ -0,0 +1,80 @@ +/* + * 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 + * + */ + +/* The purpose of this file is to download all the files we need to + do the installation. */ + +#include "win32.h" + +#include +#include +#include + +#include "resource.h" +#include "msg.h" +#include "ini.h" +#include "dialog.h" +#include "concat.h" +#include "geturl.h" +#include "state.h" +#include "mkdir.h" + +#define pi (package[i].info[package[i].trust]) + +void +do_download (HINSTANCE h) +{ + int i; + if (source == IDC_SOURCE_DOWNLOAD) + next_dialog = 0; + else + next_dialog = IDD_S_INSTALL; + + for (i=0; i= 0) + if (s.st_size == pi.install_size) + continue; + + mkdir_p (0, local); + + if (get_url_to_file (concat (MIRROR_SITE, "/", pi.install, 0), + concat (local, ".tmp", 0), + pi.install_size)) + { + package[i].action = ACTION_ERROR; + continue; + } + else + { + stat (concat (local, ".tmp", 0), &s); + if (s.st_size == pi.install_size) + { + rename (concat (local, ".tmp", 0), local); + } + else + { + note (IDS_DOWNLOAD_SHORT, local, s.st_size, pi.install_size); + package[i].action = ACTION_ERROR; + } + } + } + + dismiss_url_status_dialog (); +} diff --git a/error.c b/error.c deleted file mode 100644 index b7f782bf..00000000 --- a/error.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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 Ron Parker - * - */ - -#include -#include -#include -#include "setup.h" - -void -lowmem () -{ - fputs ("Insufficient memory.\n", stderr); - exit (1); -} - -void -winerror () -{ - LPVOID msgbuf; - int lasterr = GetLastError (); - - /* If !lasterr then assume a standard file error happened and was - already displayed. */ - if (lasterr) - { - FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER - | FORMAT_MESSAGE_FROM_SYSTEM - | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, lasterr, - MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) & msgbuf, 0, NULL); - if (msgbuf) - { - fprintf (stderr, "%s\n", (char *) msgbuf); - LocalFree (msgbuf); - } - else - fprintf (stderr, "Unexpected error #%d\n", lasterr); - } -} diff --git a/find.cc b/find.cc new file mode 100644 index 00000000..dfaef53c --- /dev/null +++ b/find.cc @@ -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 + * + */ + +/* 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 +#include + +#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/find.h b/find.h new file mode 100644 index 00000000..4c389130 --- /dev/null +++ b/find.h @@ -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 + * + */ + +/* 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/fromcwd.cc b/fromcwd.cc new file mode 100644 index 00000000..fd6d09ba --- /dev/null +++ b/fromcwd.cc @@ -0,0 +1,147 @@ +/* + * 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 + * + */ + +/* 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 +#include +#include +#include +#include + +#include "ini.h" +#include "resource.h" +#include "concat.h" +#include "state.h" +#include "dialog.h" +#include "msg.h" +#include "find.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; +} + +static char *canonicalize_version (char *v) +{ + static char nv[100]; + char *np=nv, *dp, *ov = v; + int i; + + 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; +} + +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; iinfo[trust].version) + if (strcmp (p->info[trust].version, nv) > 0) + return; + + p->info[trust].version = _strdup (nv); + 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_S_CHOOSE; + + find (".", found_file); + + return; +} diff --git a/geturl.cc b/geturl.cc new file mode 100644 index 00000000..6faa8f3a --- /dev/null +++ b/geturl.cc @@ -0,0 +1,251 @@ +/* + * 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 + * + */ + +/* 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 +#include +#include + +#include "dialog.h" +#include "geturl.h" +#include "resource.h" +#include "netio.h" +#include "msg.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: + ExitProcess(0); + } +} + +static BOOL CALLBACK +dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam) +{ + int i, j; + HWND listbox; + 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 WINAPI DWORD +dialog (void *) +{ + int rv = 0; + MSG m; + HANDLE 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); + } +} + +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 int last_tics = 0; + DWORD tics = GetTickCount(); + if (tics == start_tics) // to prevent division by zero + return; + if (tics < last_tics + 200) // to prevent flickering updates + return; + last_tics = tics; + + kbps = bytes / (tics - start_tics); + ShowWindow (gw_progress, (max_bytes > 0) ? SW_SHOW : SW_HIDE); + if (max_bytes) + { + int perc = bytes * 100 / max_bytes; + 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) +{ + init_dialog (_url, 0); + NetIO *n = NetIO::open (_url); + if (!n || !n->ok ()) + { + delete n; + 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) +{ + init_dialog (_url, expected_length); + + remove (_filename); /* but ignore errors */ + + NetIO *n = NetIO::open (_url); + if (!n || !n->ok ()) + { + delete n; + 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[2048]; + 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/geturl.h b/geturl.h new file mode 100644 index 00000000..32a7b3d8 --- /dev/null +++ b/geturl.h @@ -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 + * + */ + +/* 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/gzip.exe.gz b/gzip.exe.gz deleted file mode 100755 index 1f766ca9b6fbcbcd1b91656977c3c4c73ad9d6e2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23849 zcmV(oK=HpHiwFP!000021MFITa8p-yzw$?78yh(UhX4U?2m;)-6bvC?2(vOq#9j<2 zmTeMPf}gFY50IaX^q#>a5O!q+3q_5yNt%ysQncR9ZrhnH-C?OAnV1MJUpxG`d zJHfMUCeKx-p__)%#EW~*z3)j+w!z6vr~kAXOSNL zZ3~ML1!1wX-^2qD>?ZU-!fv*FBch6;I5;+hyO($My%E*M0qW*@@aaKuGM9?Pr*eQo25< zNZ?fdpj1U0qz+pZy?@1Wx={#+X>GSyMeBsl_K@H0h33Xux@2kfvYIN|;;OZgL^tva zfuQ82d;GGG$_D&cP5mAU08&Nwg#5Bd3C}Q*%RI zOJi*lb+$A)H@h4*N?ou_Q2S=OY4Y0@nQm!luHW3!OlvniLbud5HNkX`tY$V1!l>9S zO3ViS&aQwTECaR+36hMqA(P6_0d;7){b4!ehgm_8pUd?HyHHy}rhXY_4FnMNm9Xeh z0#(dM1gVDx1X&ExZZQ-FSAoqxuKCZnT{U>rYAV7SvTSr|720nx%+wQ9LNwTgRF&jr z`h!X!4rJg&ph9POa+jb2EE#*kK3HXY5BVDQ@!(p*+FDklo|p>3EwhG0odn5!FLNKa z-*Z#>b>PGyzt<gx)ij^{!Wp|ND)>%9{*kf@uC1#w@AYNfGEjix8fINA_<+0o_z1@BT7;5e2{OCT6UvFb22l#81VO%z>kF|9rA$ZuX`6XHO0*v>NblDjBE^31v zrXYoHwDt%uW@AGiC_6@Om{4m7I5RE`TmVHOKpL9q3-lnT+YcRbFysfOguIYw{zI+1 zfuDK2rhi!J;`S8)#vp_xzvKSTT7AHeh@$gjfbl|r;mlCGHmj6{2R?lj-6e`$**)So0|4q1B(Lbc;r<99pW&yr zKHkRT!)i1utP>KvqgK(GTQVFVK9$S|p1Noy4^tyxB@ZA)$U5x`vd zTWkqemO#6N^kY~6p1OSLnEf~J|XH8UyP0>aWryvI#iDq zsORGOkuwEO->tKZ#Gk!PaNuldG^KnP-#&tHoH({n!|!qP6{N<`cN9bCH-K@%^$I|P|{_u;3_yU&P!Li;LAy7k`-GB;=VRvA0j)>2~C^*UT@RHh(X*^0ZPEcZ|HXE`NmhE+LVl)S1{{ zv_*Xr1P^qbTT7U)$Us#(a1fkqr)g)NYJCy+rYLgFWPUznKAwuE2Cn?NmdIw`l5YV? zo?6NYfY_{(46#0LRzG<`A2+E(FN_^GsqbpzdA_09y7Q=i!#Yu$nLG1+|C}B8Gkrjr zGKe=G={2~GzK?YZyHnl81p@C3UpmX#tamGB#yPMKmN-z4>zwQRccAkPovS0N1<0yX zr?AaT&8(ZK9fe5;jzZ_~=`#EjCfq4_ppMvKr@GdvVTLEpS_S~<1zXsn7 zPr1SEVC&%{(CknC5MtG-{_XSVc-VUgdb7JS{8;7@_h&c&&C$X}YzokfT~)UM=I$iJ z8{jD`KeM3&-$v5=aggJq`h8A6JBPj*smf8G>J)#-A2&YW#Qrovr(hlM#kwvMT}3zV zZNuKv&;j_*2Oh?rqtNP)SKxxHQ_Q1cztw$;IaCw(yH}oL?m3LtiTz{O6M&Djf3&cT zPlYq4x2jLFMWq{JS2f7B-<5;^AW{AOXFy|8(~D7hdD_Cyn-O)%z+Mzm!JpOFIoVl8 zRZKpudBGwvvIs(t-9Ha&7})Epfd86AyRpgE!!dPWCZw!`_T*ryl$14Jy=z(|{`a|@W%F_69#&}gOPTConGS7!Mr`n7~P3qKV znFXBc=ig)d5wAe~SGN@Hzt4~_5Rps!6KhQm4dAd^3P{T-fftA$|1e#sevI0Dn`<*W zUg752+!p!Lbf9$S=+04f;cPZV@^Q@cYCT9!i2t&UJwCbv6BryVLZSf0V<^~3u%eRj z1|vu&%s+-=6E8PeGJ;Glu){vqS~l7O#Vu5daH`|wAsjU|CcKL%A?u-%#&WZY$~|5D zJZklo;6c_e5f4;y@?zGmBy{tJ5_EJu|0f&S{aG|+j=qZasbK5AV2<{q5$d@SO1PQr z1?eKK1#b1qGXxg@^fNkUw=?RK9n%;~;mH@~W20&Chwv>I4!%4;>no}GMqhajL}&xI z-eVkijLD|pM;}?(=4$#V6FWgclUn?Y<^)&z`3?m*-2?i%z>~_DkYC=|lg{>QLjGD4 zG8eQu*#f8X6Xbjy8E6AlJ<0jd=^1cCJBdRBIOK`1E%3x@3l6WnrLXpu$QqoJyj|E2 z85&=pcQc=ImG3B|;;h~e=~FK0*UeexTL3et+jjAlp9A^<6f}rPG*JFtEm1dnjo1tD zLZMgRGfR@dlT-b|4C6AZJPRPer)p07>;f)VbMu-ck~lS<^>-3TmxyOt$Io+wnETFf zSZ&)>Yp~l>PlH2b*R=m>zNUBuM)~Lkmi*1pzN}xxPRn;B%P%<4B4x=XFjGz85m=%U zOSW;f9@RDw3WDk!*JuObX?yG{?C7dYZ_~8FjTP~sbvfb(nVZf2tot}fU^}Dh_mXbw}2s& z0lCIwRJu&9guOy_yfDA-Ai#-+i!h}Q|APpS=|V^w)hWI@^@%v>jo<)b4V8s*zqa1u zMaK1>h--#dAB^i*#TNTT9MlXpiB zWgMsrn(06>fMim+mnyT|;@c=@3mm;huZt$gJ4H2oG} zN_8r|NB3uKgBz@KxT(0&n`Lrp2E>scUgK)4J<+wzI>>u8)qg zV}v-k?a|!(zgAaVDT;3|RU3ipZC2>TE7oyDna0X%tXN&G>H-)~-wKV}pF|h9#s%%z zN38JY-A8OP`w-w`AK90=&y0Ms1oH6*Hps_svdazB{B6hkZ4jQuw0tY{xuGwi0`Dw(;T<6>t_z&w`J5%SF?<%4@?J}Y*a)AWqiTt8rmU8%g5Xt{jw@x0M{%FISm{S)=*;!6|>W19` zm;)iVR;Px~XZ^z5i>G+?XMmECm3ijq5A;Gn9bhb2%tjL|kDkKrtl5~U8)6$rPT>vH ziGth`0~$%lCq+@&Ar&CyC&S$sJ|*Q@3z zUhl*!+IZ01ft&KLXv{LVM*TZtC<5OYQ_YcTW0bE4g@#`uT0QDI^)3XC`q4H3yNj{6 z#$K$-vtt)eod=5XL(25zJs>!ie`FDS_0<)md!YV#E1#ryM=!}+w8W&`u9vdPVjY6! zxs2M`bF}-(ce5B&lEom_O3#X2t>&cycL-+I55I%nnGpX&+x~fRGVfKQ=ku}q-zmzz zpc~H$uz6llrjoeF@b3pf5B2Wzca@Cc$McCOb%c7l@cR4aoVoFDJRb?PQwhj^YnKp` z8L@V(xw#@=>HLI#=?MtlFkQ0OvUd`Zx=olK{O4h6Q6`>Brxo|gAp!Ii18x*#QD}RQ zEQTjN=HYJwN*Djp0Dq$c&Df%O8V?33obJ3Lac;;jAoJ#ud9RRpM@Wf2E1n7cl4h%5 zs8f)~+BZX*{Yekkx_Ltt6bXVqfIpRag;2ZT6|=e;?z{B-;nEV3yiTu;S0}M>TV04n zTzKl?{w^qf>;u@BF5PKT@7cmCw!YJSE!Pc{q18K0>BgI}5>;)TkTraJ4&`kuK7ss% zPM&aF?{k_)3-K(#D%^x}ofWC4{;-r^Z$Om>*@i_87NN#Ko(sgMJ_kBBY#1>|{~k|} z20hH?<6~7`&UJ{Lj#aR#_=_Uh(v*WS%ZyR{`vZ7Cf@j{rbDi2Xrg4Vbw3YU?4DmV2 zV2<-Gg!DOvV4ACrAu3nofCPviJ_rI~C{JE#96FdYv+n>a=viKftie4sF#s|D=~m92 zlGm7zJBD)4pgAHeOvLmFM9e76HPkfo@fQt-G6Vj>I*MDktdK%Nm+yScH^~w<>;eh$lto013K9j&8dCFM5s>IY45*b#3|W#85={0c zU`a?=R&#T^m{$2pTT#+zi`80uU z-@m?}U-Frqd+$8XnKNf*&di)SqdA_$tcpmG2i8419jw^-MJ5qS1sP+aeb$dMtJnc{I z`y=29U7dJpa6cz3w#Q)#m5_80p+Jm5LaT5yV24rsofhp6?Yd1tK<|hGC_V2Zd7w9a zZPt~&sc>z5Sg#OTm>I~{H9>5Bd3~VxP2-U(zS2L< z4D4Tn627y3Xc6x+j%dCK&Z-QMXSkdvGL1%VU0V7YBS+&qN7_)FBE}ih^V6A96KaGp zZ75^V{61i**Qh8n&M@YqW{Aw9_W6aFQG>MR==M~xy$K~0B$Q*W$ zR-BD1NY%Keq<7%-T3IU7J3#8^vQ^n`YHtGq$0D)S65i&-~lfS4`uI^V3zc8z73q&e^sO|grykShoU16x013uTOA^8{QY_AmWTtlrWP zAfM4nB6zgaHj34eV6sd`FZ&`S)ue9xzwX@l}dSNg{GL5r`0^b(F&DY&3PBsy^BY{XOrxg`Ay-O z(Fss9CHLVXiMD0lOb^#%#P&qYANC)QM{LF+sZ)r^oP#kRxR07YOuw1jdRasB0Bvw^Tep`&st^^b|Q7qVgEk)LWu<{=$Q?_$2rhJ`;-vM2K!4fL^SMc@w470fo&f z68Umf;+6*CyqG%RNgi4KBxF*$p63M30*F8>0r15l z&(0r$jlI)D<*=GxFTj|WYs)ic*$Ogptlu%q_OAcrt|CuS#4SK(!Fg;rm&*-WBFb2w zRbVTK^`3uNl}9H8in0naakJ5{w|Wz8app$fZRCa_YTgjwonZaLveT$)km6j?AcsHh zT|sqCQS@6btiz?dpXnV_Ro;cBa#~E&C~MU%>%7gO-K!oj8}d>@e>s40ab?=bKHLk5 zyEEg{oX|D{hL1WKYf7iQUKAui!G!cH64N`TwGG1K=3vs?0JyM zZ&z$0#Ro+dG3s;_{uV1E;HS7LS(OH{tfFHbG_Sz*?ew6;iy?6ps`$}LqivagEB;&_ zs%muSc~|LUGfRU~j>43_w^@0}nJ)*IKW}J(h_nEgWO{gS#lD*BeHxbM)gruY$PIMFoNZnM>%Tr zbx8&b{ESclwdK&ZE^RDP1yd7xH^=*Q6D1o9h2b9ew`Y0u00u1>2|vf!H3+ z3EIAzgmG)!koXXeBQ(jew?qc6PHn-%u1cJnAg?{@A>zD-aRRq>BnKwAa7=tpboL@{ z4UuB2=r|3J%8m_0x)+9A&G0xCAhBsKpzN#}fN;w)*|mmoeWxwFMRUh((hkf*qSO|r z<_?SeE<{)+_kN0n*12Mopny`}5>)E;HA<=Nha;)r5)sTI@6ATyx&6dDOMqD5HVAaS zd;*@mLmKWcR2^wTeY6zD|Dh?eHQP&445?bj+JnI&o3oL{AY;;it}0~{2?)5=7l7YV zAX$oJ;E`579#}!T8iJe2a=60*THsn|MIByK^OjJ<i z@!WEG)&!^&q^Hw-*&-L>t~SU(RqIK2tqv!94YWNyu_ATgiVVXNlyIQ5IymTbyr0r0 z)^Q9=WMZHO>BUN1p@xDamR-V>Vw95f4S1mMYd%wqqbCPhe!!@3b+9}KA4RH$BiXHqUEWU4R zAHp9?TVot%uqj2zB?J_PzVnD{x9JTS#CjL6)1AIkp;Y^8RRr48rBhYZK(aRYl0 z^{-!bMt;ibb8~2OJXakLG2mH)&+DKh@T|q>O7#ra8rKNw5A6NJ z1P#2aaH7qo-KEIJFFl5xAjfl=mJd+%tN}iHj#tlYi&x~M5S+1(W*xDS(4#Bv8szt{n1-06`w&>Q0kb>K=&7&OjBETNBq64$ z>LR4o`X25#^GDprHjzHi^XpJldqsY6{2;}a(^NxwgUZ)I14YEZh`zzuh6-f zD}`YeD~FNr_&&pN;M(b>N(Aw5{`tPXPO~fy3sM+voz9h7Ma>ddsI^tIgyW!pp@2`s zlLs+_n9i8vl@NbSaQu-Je5OWOjo9^b^T^+ERt6NU43!Ed~qe zG(}Jq9`jb6&R=z|P(EZP5%h$YpoLeg*TM81-`Q|B6IYGlF_u7cfh!Qf`Z-F0 z50Qu)haH$&|MWxfCcgqR?w%crzNZ*BlP%ZzYC)QfHA?A#J_=8HYrw}zjIq9(p~QD> z_g7)fn?evsL890e-4RC&_LCI3c?G0z_3>A0p-ODEd(^C`!Wbz6(SQ_3;?SN=VF+PV zg&EnA1<%8qsa5~f89Iccwy<>0`8@F$V@185Do=r-m7*|pd~_S@M!!^v^dVSZ=zohJ z3DX7CQlU%OrBsJ=nTpCGM)}xCzXcc76;`^UicjkXF_9~uIvLwC`nn*1Ri}*b&Yi!9 zF}DxSlQFex6f{e~6Z<9HfW&W%>4O+|{H5<>++C=6L`aUk0?CaLib(%m2woT-$k)O4 zWk}zNwB~fxyV-!rakx%xwa0z&8Oet`;d6Db2RcN@O+f6J<1y!BylQgdbERj1$Ddx+ ztSor6ciG)s$&`KgTwm&n=i2`fIR6*FD%YtJ?-efCTQ&3TmnW1Q6u+WqF`n|p1`p(X zJcxh9z1&&IzoL8S{7(;+f7m^ke-q}fFFDxg3A10GwCO=-WDPC61&`mNo8{fu6((** zQ1+g%0662sX6I9-|B3g_uf(tJDc8pP@}E?4a4)W6*I(NePwn5@O6^BwZ}M#VI;OM! zv5(_})<0mV+pgu3tey}9q$umhU6hh9Vb}wI)6G^XY7~49NQLo-LHtA(rR1ztq$p+m z*Wk4GCP*>DmxADHwuiC!7=hxCp!k!$@ePCHYgzos-uM_H6W?MwGgm@9`8hQ)S@Y?kmbqMwrO_IHTQpv}16c*U0(iJGr?7bF+DeP41Pn?MN z(n~}1+IuaM^2Et_|N3cg_-G8@b?R#2Eg`!-IL&|x6i-{LSDqj-uFFGS8}oKDuabGC z;I)J_z%Q@N&%N>%w1;|Q7p_z3q{vFXQ%oI@qKrMz`L>IxZvE5c>^!BZz4#~2dwHo? zD<+?oW;rQ|ZU=f+DYDKgX`Z&4n(__8$cnOfNImCC{4G*TD^5dig^IPl$WKD#tr&Tx zFq%a^gg;X1z#Pq8g%d!UK7=tvU7eKb7FX!_PE)&n>n~8`OC8ulfXzBFvMflA(tF;8 znz#WAu>df2OBS7&+9xd-D<=0!mPp!(L7_5U(`xP_J~zwIy#sj0**^Kg$KQ=WZ%MO_ zz$OoXtT$JMq4UaAm{Yg@=~r=hL86Q1PoyZU1TnRvQcCV-WCcuSmFw%~y{Uqq%_`>t zJ~sJuNvOx%B_$(itm5L`s#u|SliBLgBy(NZL&OSw8zVpl6nmrFfCkds%@ENUsfQ6` zx7eZoOA`;E%rdT$NU1Vq&b#%0>EKs%c+A~p#odUbe(QQ9S#pOMfk;W_Plz=na~F;s zzb8rT^j-wWH;Cr}nV|k?q18Tj5odE-J-S6!`@BUe6+9X2=B~?|PC#78QCm6{y3#j4 zokhqy&f5~jR`I+ixm!wANHDQ7c17=|X;21z-2>ZIrgv>)#UofUc#r%o7N?aFV!P@- z$9dtf=w2xNg^=}&waWgKaWD2+P|Z%E3wiPDJshhxtD3hrs;qnijG-xs_DlMb|HO30 zuF!3ouFOa3=Dn!Gk;TF{0MwaFf!Z_WKMcoat$7jJbP_}^Iq4UruVxPb_$#JUvS_3^ z#AJq;1{nJ2P;qjf>Ah-fIrVWWl(pfh_^x_nZI}-LIbY;#QI!_7Fk@98`vFQkIX%aq*>&6lSjjqXjb7Mbm z@8?P;1oUqy%jG?6cg5c9+4NN<>ocTD*JFjV=CX+8T8*Ew`Q@?*@vD$3dk`;_t7c=6 zIMFc?iy^DTSq@A`l!HD3ntz{Ft$7hD=(&o>;T4(@bDHv1Q(2|t zKH!`eRg%yrQhxJAp%1~0SI~s?>>pbDm>VN69@2agqaEQt0@1syOcRBc_TZ#&f_46r_9 zkp8_eAa*1`Y<=A$b)nEj6l+W!wj$H9;&3akbF751z;!#G|A;laZCYSn`UJ!4P7E1a zX}=i0X*j&Tgs;P3{PKj*_+fU(90jxtfoQpm;(1etFao}X`o8IuGEmVxI1kgApuuiU z_xRU!gZDQWH6R&neq*!P8%8ZHUWFSp$?kg0%5hW(-;1D0`$r){kB+AzCrQa#31;hc zwl_jyyb;{RTGIvn7Ch{4YA(LTIqLwYoFCHHJ^2`v#{xbU+#(MTqp|v4;h#Mssgl?d zVvA4Pj7|-uxmRCTi3yhK>q=RIk3%VezAohVEF&VFMQ#d3l@4dpx2{-wfA}U`t@?u! z;U$Vtg%Q*kVLW{MlM=Rz!WPnp8crZ!ngEfg-99D0`b=5^S>L<(1; z5?N!BM?z%hJ-mggKi)!I5pR(nh7u6X7#&~r=P{8L$ljpl+XyN7=ieZaar;mwAJ^b2 zDt-<_LQ|TbLs^O7f&2T4{uhdpz^+oNw!ECQARWg^ycG1%D>)JNPLwlUsruS7obW8d z&T7>OT%04}f0({@GtOsRItn<&#f2IX(}0WblMzu$VtD#NtC@2OBnBeuB)R^O54v+CrmjR4{%q*IF z+4!S*CXsKnUkWYh6aQwvv}w}>@gha=%9l#`CJ6sPVf6{(S1d}QH=G5Od?o&^@vO>p zSxW8I{}-Mswu-9YRSUug2i2o6Q8jX;Xjg5(?kQp>{My3nE%$+_glogJhUe{{brOZw z8%UcE^YZETE0Az zcP4l@B6ni&J`66`jB_RgZ`b^68r!a!!uhsq#s+WKn5N-690b!WOkek5bYuG^=e)39 zrGzeB`@ftTy>-}Ze5=No0rEfT_o3*Ws-yMCBla$SSaV|!&v)XS_$+DYK_m39XQmJ^ zyIWgQ6j!}=jSvf}H78v4OJ}=x~)ZEJNENkBN-(A+*#j@aBEh60U9#2K{tVMNxvJx>-F&VYz?9;E0Fi10W|$})N;KOkv=H!0~6mtDk@Y_@ShHaN1OlfK_K9@y7I z3I|igw_Sq@%%g&iGhys070W_lI@!fnchP#a?dHHJ4cS5VZx;qBc#UiLQq7Xy^p5u^ z!S(ON(-BE!+Z9b&=2?wvGuGziZ}^@AhFQ6+N(b3sB9okJ(`?4VtURhlE+-?`I4x(@ zt;T|^C-6Zz4|~=05P!8T)3`RP0J2HX%ZfW**%_Xn!e`*>k05Hf^1TJV zi-9cvA)OfkHWqG>ADsxIgj+3yXGZ44b3KcBvLUhs{mgj$au*$AM%?i9^NlRrflI{- zIDPG;CmC+#EHP3(s~1w|0oS#oru59Nsup*m9^%qBQPI=rc775j}VdgXul} zmKUfgQZ5RRtK~ykEJ?}C$_Z?A{CuN+3VjMQn7>x2ZT?1KgVgg15122wN+>^txol4m9>M3^u2%jD zLGbki{~LhchX4TnfEWG+FZ^%4@GpDed;AQT4Kp(ss^pQ(=$xt57LnP7Eh_cMp;c>)idly~_~%G0DL#&3UlBZ0@jf;d0o zUV7CK!n1Zq*I>N$Gg*Nc#70WXo2Yd8CnTbI;}et5{6}N52NR0f>EtlvUCB!)E34N>q(eWCUnc-RrzZZ7kugO_S zp@^9NX<0-2aT0NhWZSX-KCxyevespfe#=`BC>=m>jsI4O2QuNI=RVx1IxjjgE6MS^ z4;8xugEgW9F^E?1z+aC8Gcaw#=R%cuOu>dtRi-h*C-J!aAcO~0EI<t-s_!Tb`chUC>B8f;1R%6iDwz25b@EF0c zHWo*s4vS$U)!-MHjQ^Q6rR~Ijk5Dbq?>uQhqGl$}Y7;lMX%xVe1>eZnQ~&gDzeUi* zl}-XdUFgjYj9dPWbIXoi;)il7BSy%dARZy4>_^fWRz2G}uhlE5hT3Cjtl3bI6o-o@ zyY)q?-TvaR20N%wh_1fw8ldkqyhcoT4Uo#MEa;Tio68Qoe1>^k+B9ll=$@q*>SYgw7!TlNQUlqzR;uAaQ zE{Km@&`7MY5sUFHrVm-|<{u4ekN9a}`^)|g(ZPC7BlQ>5!xFBIF5W>83^(B)3^?Ud zp)eIPWDFZysM~DsS}>(e+J*&=)r_{?W&bnv9#V~O;PVjUDAcGa^$`G5cCZW~rO@JW zQg?L#e?5A~U%tggOl(s_;}-P>`mGaiGmZv{m`E*Z>>I(fDQ*n2JMOx7<2{Ic`0&O&0qu6LDKiS?jti@-f zVKfMtTSlS;*MK2tsG-H)tTpxLH;RHRLT2VZDOuLnSv2}OO);VtUEDq8h!dn0+@OmT zFSf6hP3G=`hXAtJ3b6hC;}3+dxeEN^NCkz|(~?<+s!!FCVQjl6UBBg4JeFzx1M%t8e^-5^_K6pz6>fc9q6Tn^ZuTOGz@cW^qMN<)S=m2u)jxKHyKvYcoH9k9 za)nD~H+yc4Egldr7OJIWRCg6Wh%O$8?l8IYjmw>Oru1ue^Zg+fX2W+5$MMB(Jis#+ z6=E(P#P1cFJCg8h!$RR3G1XmG?52%{NJvPNGg)Wgyt=DQThNhB3N!{&YIniI$Sxlt zjS7D(eNK$H3cnbbTQ$T|#!^Uk6q?7x2?J!VB*K@Z5HutB^~ z_HVpbv+<0&^8SLz_eDWZ?q-Cz&SuP#WeueydT{^tr`km zSYZP+9kF+>g^rGlOeniZm6SXnjAF!>brC*ggT^yjyGwh&fJ#OpQCB2#Q$xX7XZO(h z4P~cygLJms>0A%hx-7+6QwqNGz()Api>&Q*?8nV%#F)t(wil z@Jh=#W&fvHQEVJ5o}=*s!ow(>v>7R!6dA{e9gt5UhHELDv=_gs4`b6ez-9T8%vzW} zXRgN|9+$B2WTVr8*jnVnz3d47L`SFI@dhU90C5!yvcraEpU-*m*KEdv_wjc3q>``e zLnwEQkg_CmCbXc;KFB?r%f8l|Z;m%#G^RgFa;&GXg>LxT;aV)7mnby|S{s?Sj(IHF zCbwcm(WYff0TU{{L9^T_X;EzXCN~cL&X?!)`v!Wty=CpXoD3V@2W6uh^KAJU8R1-D z2wrfPmYbfT1S$JLWv5pv>j$&3`lUE(XqPob%W+3x(0Kks`Sb9wA^1~+?M?hlblbZo zH=Yd%!CJAO2?1E5qZ_1_qEv+V-)esk`~Z0I1WPSCx)9bvWxwPHj(^%A@>l!w*EgQk z;4J%$rtAO~g|u89GKy?Zb)Y`S0R(!j{;Bsu$lT#J9rBt}i@fG=lNc@2{Ng2=2hhZs zzU%FOqBdoqm?#_u(Z_ySRdhd5&1+BOhn460p~|CT<&g;Ro?CGV`ixqNER#qy#bSoR z6u;7rii^n>3hjzEV=tgOqn^r*#B>xlQ z+X(T<@&u9Id!kjyXBf?(ckCnP;ER?L=094V(S#1cAH2dJ4E!bg7wX2dD*G9gbKXdG ztm8B>y9<$MQj3JHe#9afH!ddI5@ zlP|(@K>zte<)4u6;BO!PVZh74;(_?z5{&;}IY0gk^I&-l#s|8R8RX5L-w~>z|E>1; ztY!#&LkHu#sqt)>{Y)6(JKT#eUPxqb8qV;wO$o+TJRg7`qb@Ec_ECRxnp*AvwcIGw zE~7@|+`$@K^H-3Z2860gocqzJFjOlYG|EcUlUq{c$9nv&)rec5)LNfMgI70h4qOoz zZuK|dWPs}WMb)zi(V;3Ay79a}OWhMkc3nOTh zn|!L53;=k6xAkJ#FuiM`#Ne`i!=fbcM*OJPJ5DS5Oyj*FPRfGiUe?Qo>1PMc$3eb@ zv6e(FCe%7Q1#{((dEBM9M43i77*WSf9p5gC>)+(xs;(us8i3mDtP<4t~rQDeRZR3a3dCSSFu5 z?M!qp6r1esu%d573L$86h>95|Rct!=d`rN2nDVy9FSWO;lb|l|hzVj7f)0Dqjt>)34;uj`SkB7K8DN5H+jhsAiq=b_tNaWX=%thGNr~&m7jrd zu?d)rtf=vYqZy^z==3k;SlC3L$jCG;QH3!pgi~ZxwNnU-$guq~#8qEQFaq=gnH37O zcQMsM`-qCw3%s#}!dTrX{C0(X@qqMqTj*@KECQ#|wFt}@(in=t!j!zPxoX}4=OIWR zNm^m>T6$vgguQqG^=-GQY5gG@8JKTLS+-pMauIO(5!U8(PcydZXsE@=#e@oi#gwkF;pUz&ziRgn+Q z3lW)r+=}|coMOXFC(RLON@lkw+3jf95RqAfp-v?<47V~u?JXK0k-fN&E4fqY))aJJ z!HhrVn;>g(3`Fy_-wHCOcF}I`^N8)6jsY7T=y}wmd*_$*Ag|EdA zmCaZ4fS+M}8dr2@Y$|C>1{v?Vy)tk-ya2_QTlO$>FoSOEz!x%k8K6&2yW-ehgd4mU z@C9a`89^K*ETw<$@d z-JY{*#O1vi{#5HgcOrW*wE0n~(hFLci-;(l=~R ze#{`YU2usVjqb^fmqMeP#3SNIzq#NMn;o4S;-&f81&#)BzIMY+vGd1n93zFcaMPvG z(mCO_ka#iFHEvmUxJ$h(d%8S-D!U{mjG}l#FLb)*g1kILdgBo3jdEyUdZQQcyx2h(##is6%Rw)f$M_Kc>3=PCdK~0T&Gx_L3<*s>8$$}S3#6cLm6+C ztDm#{SBD#CJgnG?55BclS+A&i{#}LtZezm&zGrs*IH>bt2pFc;l(q zHm#I~TcmTFy=$fIZr>G=*9EopmCpnc{dJ~DHAHilA~0Y3=aWTxXf>ap1J)TQ>=z9s zGqVj#g0y9VGJVJxWN&OLPVGsSZ8dkG*)=@InfiXKxeXT)#pEs+V3>(c<%mGHPp7J} zOD&q^DlAp2`4f&**KA?%NRt+G_g*wKAbzwD*C7Y?#FMs+n0kavr3CbUt{GV6d#Fc@ZrA# zkHbnU+Wgdls0y{54~+GQZ9p^Vi=x}5RN48!c#oJW_e7)hL(E@FZ3C*sN4JUQ(^9f* zN7CG#f-Uk4%2)VwjZWRdR%*X!-Y-CW7Fz&}j*B#FX}r-)L!p&t1tx^;}* zNKwx{OV%_I6^oqCaH&Xk-&a0DTG7WaEu69k8IG8d+GmAk_~tx`d}y$D}L+bje_wMdl}g zShNCBEi3M(XXV#TmJAUgzCUx|;qnD&{T_tk$(@IPk2>F#gnd$L-WF51N0X0Y!+k!I+bgR*3hd z%RsRofOBy2?Z`b%6g{EWs|RFT0HG1`sGk1fKkc5>#Or)VD{oS;56*9#Hz`O(m`7 zUd@%~eN$m-&?{E1zl_VTm$tm<);YKsYX7_jBVPIw$qmF8^ns-Cu!`6Csj zSnu3B4Xq^lXH|z=`jfBJizvWgve~Lg?S${vyu?v_DKDMPXi5n6bS{Yibf3 zMf$Sw&*FPk1eBshca%4_e~I(6wkb#SwY!n}$g#ttzb-%7F84f3y0LEYGcTKKQ00%C z?_AHD2>0UU!TVi55Z_g22H{IM;cXh|n|e3aN<@q*Lh`G2d5Sw$Q-jQ@-;DMzV$B13 z$J0<*v9qx{^bR{b%V!{0T8lD;#M5cI%$3hWbFTY}oxb)O5e(KpX7-2i0J$-Qtu0!s z@u?~veqh|m3X~V3o2zDeV-2GOLH7y;7ZmRg;pGkg@%3|<)PBi>YX#N#OlC>#{n}~- zwW(T)K%W3apA_k(T~@#-Mv8HMqOY5TUr31<*f_eez273=;R%?W46%A>%<1v2om z4P<{9V<)DqGTN9K-b%JV&Ux+YQVW-o4bW61AyRZ8>79;^9@1yT=j6{shXr4ch}&!) z(w*}J>SJ45H4k!JlD*$h*ca0oy8|;Qm?FOGTQ9D`RQg)Y9Z6P?CXq$R?~!UOq-#s? zt)im@v;JVO>WcnWU#Gc-2oZfU393Y`8DkaajZxW~R0#5OtG)OIWP_Jp1UA?WZG;X` z?qhm&t30$P4ZqR!Y-%owV}K7~1cHY4{wkap+U~ZBnlTa;TXaJY*OdgIqFx73u{-c% zVLN~ucxEM3s(nq(_fYl-91Vi-hJe@21zC8bj;>B7ox&_$`VN+fB`S`)+@= zSXovQu>lnN=Si_UFlzq4deCS>B`dM`q1Y?-x66_fquoN}b4DiER!R=U)u|)vab(}g zeitW9v9|Jbno=x76PQ*O3+=*)Di1w7YOvI{k@`B7Gt!I}-(31icD|Q=fX?{*y}}z- z$(c!rg+nHf5TXw-L`ysjaiS?BoPP6XXtv?yd45wFf%ZYs21ts$21X6v8sL(YnDg>O z_@&u&xp<;@PIT|-g+9yQ9$GZvT%xII;{~x}4@w++uMG*3XP`v(FUdO5H$7mu;eUNng3IA)6wJ1QH$J zU!K-XqZ;o=$;6Q5@>~6ZrdERO4dD2jJxre2A3(bK@L@7xv-dL4rGAB$PAy1ieuDcR8}45JA4*~lzF~Ib)hKn z5}p68Y|*Gtkid^6UuWWx{A?Y~BQlX{a@?gLJ0k(>*Hs2JZB@*Lj=v7Duf}&q`r-AM zmhSSc%vNWIWRI3{KUKD%!AVcHCVPY&LRUJB^+aGQ#)ya5d2(5!uWLXWBQ9nAh*;rW zellwZk@+h0jl*1%`bGg7TvysZRciMT)`!1}BMRqUt%@1EtJZHsQMVVm ze1UD%b=sotO_3`Qm!|TQiUjDKr~-<2T& z`%}!m35K8n`A$jDEpRkY%=M@rSknmgz*DSnz~G6>!M)%eD)&!yDfR2%*p z1Yholnv28w^;(!k=&p^VuU0e?vQ0Ae3nyJ`l>U4Aw-^UAl7EFO2Tfu}blU=gNe~$< zir{EiUsd_t_}LB$CE)ztlCelD4ff(ZsKO?6P+njT;)r zh0%@%o1X1!rO5OCNn7DnD+w{%5fYbBCH%_sW>Ts)=4ge=6-Mh5ss!Aya5Hl_wEjp} zF6&C~;%sBZ^ZJ7-(-C2q*aq_$jGqYKg)gx-1MKZl`>JGB2onS6#5q;F-i_y+i=P@0 zTdH=V82KJd910@E^AazO7HJP;q`gODdN2Qs6oo1AIv}@m;&ahQc#sqEi*xaF1E%*1 z2Hl5uWqNTo0;pn1>IN8mNO%n!->-ST3DNrYa4Re zIS5Aj|1dqI&d+#U$byOA_a+QTkM~Zb=dI4odIFFC2NouryJ|Qg8_o!jm6MaPIxWW= zHhsErTDr2|6M)}PsCnaFF&@S=q*T8IJVT5FeX^A`R(z|*`mL^HeaAZFvQ$HbYVLGl zG%ZmlR+l3Gq#9heLwlNgi=achknqW4Hn=8d{^k{sd{yDf4T3gJOoNM=si8Pk>sWgk zRyqgfP-{^aCl0^!LILC35QJ+R7aM|@fH;cxS!vn*KCaQEzl;Hsqv*sFNbgO7EI3gjFo!w;UB_NRyC2xGO}v{XN??IH!NfS4gHLy;;L4 z>phV%4KR}EN-s{QTgT{(%RCj&YSJ8u2f^;a6K9y#M;pE44)_N2nQj{{nI~eT>u}3G z4pRji5Nb8|GVe4k@9_6jgl&O(o*O58?M7nP9&bQ3HIO2;!FKSvRpLT^oHas&{ zW^XY_BOFI<2~re-fk{rAW$6<6?_tVaKSC$5i`XCCEQMO+H`sAHAnuNYQtRF=%wUJ2YQnI6XOvqKmbIR!NxL)H=3dx-mb zW~deX^;=fcZop|Vd4Mq>>H?u(dN+)TTWKAxS6ZZj!i;d^M0 zJFg6H@|rG8fovtiQi-=@wgutz8)p2?bpz%XzC?eJvtT-iXZTZKyvLatFa`JLF8Xor zS&xTml6&nNG`x_HEnp&R8H5yGm_V%dpih5F!EXxk!s5*XL?}xTFimJ6p>Fm8gL!(X z=`O})3+!EY^`KCt#M1aoln~RE}m%j-=_)%yG!rDV*#b>Rd)#n%oz{BW97O8@jQwV zBUtyq;JH>Zj*UW)(A%{pMf%-$f76MP_{%P+m_t`@V46O8bCmutM2U$91grSKAK z1Ij3&KWKLOrvjD!^E zn!b{h@#&U_OJ!f8nfC%!^zpJ*v>z``LPO|QXo}VyEr!fnxxSc&3|ycm%d@O&9-6Msu^rk zf5uwDma(3@tsp=BwxX=u0%4uv&B){eblcEu=q@th{x;6Vqv)|dgtj-M_LE=TfopyH zag2(Z3A3iXBXImZfkT*iK#ZD&pWd$lZr+XYa%wQ%Cz#m@{CEUE&U+g_cHzf*9LV0M z94Y2u{D?eL-G(1G(#HlI;QDZ#kCV}AaP_SKq@E+?mFjMc*MKQxe8Rg?s!!und^=i7 zXVVjs&8g-i@m4!TP5y%CxFFkh#J4LT4&G2jaZ=lOc5#eZAz zUsL>zia$~DI~0Ge;#Vqux#H(2{!5B)Q~Z^RzhCihRs8oAf4AZvR{ULxU$6M96n~52 zmn#1Cia%5FPbmI6#qU!5BZ_ZP{KbmDK=F4f{%PiW@E{nToo4!@SX$i#(?+5;3fyW=Yks_@O~e-$bk39!9@&u zR|mZ3qv{9HnOELZz+D*a54V9k8}R-BxPJ${7lJz#@V*S(#{us#;Qk))ZUT2K;Qe86 z?+3ttYzX?VToljk90&CaP6MuCEYvr+cyJuJo!7uKI1XIH7zhIw56%d#D+Q@uuxesT=bH~8pow7&3y#uak#+7mKd&h0;yBE)6bK|-9z`XGoIoW=;h;2XFf`Nt1( zszFXY$Y}<-kU{Q;!W*3b;QT@r7p6F^;)W?MTyet{r&C;n;{Lb(yf`8bXx0;L^`b#k z)U3jDaC$HAo&+BJES^I|kNTvMqd0BYu+Z?3;ToMfLN$Wd zU$yT-Ge@J8cde4gFojOx3f+b)bkr$$M<`_&q0n7V-;v8gA-xvTheMhO_&yTwx`vy; zP3ER@w{UlGv0M`L66st4XXmQ9X6_%zXG7K~`&TLdYUN*}{D&z2*k`6wJO)1uU`GJd zaoiN>JrbbDE#n%2u4OzhvYOZMp}dyY@dkb@Z{%n4@%+j_h+aru2%%ISED@FoONHec z4s_4~ln6?thHyQU?{01r=ixlON9_so=slA?cY8MBsNtohcMSQjnPEk@rj0nWcge8d zj61wG?CHMjb+cbi@2TFl>V@0OJ4d`!|H+1Hd;Z>4e)9Npw=Aw5c3|ThC1KO+|NW~; zhbmVY>L#5t?#^ED_@1vnOE|ct_{7KKUEQCqT~c$Ruhr3RU$#AGbi=MStDd;{*te&T zW>nn&2p@SeCp0}hPJii}2(9yoF*o+-hOEWi2`m4e|M=?PAL~}nz2}7H-ftZd$Jf+^ zzkF#|&Fq}*Zzg_tbYExu#r?1SBd6nb;gM734EsU`re*0_3&HEezR@w2l|%})W1-#x=C9e^5~lBW~^CV=wjheb}Dela(}ZGI!Se^3{KCt6%wX!F0{Me@;^0@#y04 zKONl|@#);hLo9zvP~B)S3_tj!QFnA&P3H2q9C^lJC#-v3>`wdJh>M^7eEZRp(bsKn z+x_;gk6N#Zd+VXHh_`3NK60S$&pCS=jQ0Bf)V_7-x4JKC)xSOdhRt-(-@p7z(eWKo zH*{+3V?HSuH9Y+vTVhu|`_t^T5xXAFeq#6sBf58ZhCOrR>s6G&ci(&Gn+ra^C8A^T zgz&$dU!=Zs7>+IItm<TDtWnYF4{LWezn_njkLj@4oLqnC3bn-?A07WqW|7q8#)#xLefsMY;$ z>+xSl9Q^w~>&||%amuOA;U|u_KbiQ&iLcymeVUnT|9J9W#~dvC*$sQne_pgZujrn- zvHyBlTfQz^?|C;i)cVM9ex&DxjHk0+f6U$PS(9e|AZN__FT!`8IUe!R19r`QO>e19 zX*aC?%xKYo2f_FEJSY8NyBc9Aux*{ojo6 z?eynYmn!-&?28ai2W~95>%rX$ZVtG3a0|d$z&!$P6}VDxmEd-P+YN3%xWnMuzayS3Y2zF7g!|5wWv!ae$EMt**79z0(I&ui1NaB9Pihv$N##{`@w zE#)3fw{2LL@hCiB7H%gVBlUIG`&qk3Krz5)-p7BmdEL`FZIX1qIxE3Im71s9#9$xp}$i z8&(%(<@!QasxsDR!31fY%4*FK3NmTFq_VEguoZBE3J>&9akx^IbzOc|t_{nuMP)@5 zT24|~3v6jNZifn@XXN5EitAKm6{Oj08}K<)ol}sJv4#r+ALD7&YklQ3sMlt!OkR2^i0HWA3n3>T#s7F&B@ALgU|m_3sjFDby0qnErYv`zbC_%oVQBI w$yh*VP7-hu7xI6?F}91D0er_r!uy(x{M?M3J8q{B{|Ep69|$}(Kmfb|0Mx%eT>t<8 diff --git a/ini.cc b/ini.cc new file mode 100644 index 00000000..3cfc6dc7 --- /dev/null +++ b/ini.cc @@ -0,0 +1,108 @@ +/* + * 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 + * + */ + +/* 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 +#include + +#include "ini.h" +#include "resource.h" +#include "concat.h" +#include "state.h" +#include "geturl.h" +#include "dialog.h" +#include "msg.h" +#include "mkdir.h" + +unsigned int setup_timestamp = 0; + +extern "C" int yyparse (); +/* extern int yydebug; */ + +void +do_ini (HINSTANCE h) +{ + char *ini_file = get_url_to_string (concat (MIRROR_SITE, "/setup.ini", 0)); + + if (!ini_file) + fatal (IDS_SETUPINI_MISSING, MIRROR_SITE); + + ini_init (ini_file); + + setup_timestamp = 0; + /* yydebug = 0;*/ + yyparse(); + + mkdir_p (1, concat (root_dir, "/etc/setup", 0)); + + unsigned int old_timestamp = 0; + FILE *ots = fopen (concat (root_dir, "/etc/setup/timestamp", 0), "rt"); + if (ots) + { + fscanf (ots, "%u", &old_timestamp); + fclose (ots); + if (old_timestamp && setup_timestamp + && (old_timestamp > setup_timestamp)) + { + int yn = yesno (IDS_OLD_SETUPINI); + if (yn == IDNO) + ExitProcess (0); + } + } + if (setup_timestamp) + { + FILE *nts = fopen (concat (root_dir, "/etc/setup/timestamp", 0), "wt"); + if (nts) + { + fprintf (nts, "%u", setup_timestamp); + fclose (nts); + } + } + + next_dialog = IDD_S_CHOOSE; +} + +extern "C" int yyerror (char *s) +{ + MessageBox (0, s, "Parse Error", 0); + ExitProcess (0); +} + +extern "C" int fprintf(FILE *f, const char *s, ...); + +int +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); + MessageBox (0, buf, "Cygwin Setup", 0); + } + else + { + rv = vfprintf (f, fmt, args); + } + return rv; +} diff --git a/ini.h b/ini.h new file mode 100644 index 00000000..25c8ee4b --- /dev/null +++ b/ini.h @@ -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 + * + */ + +/* 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 ACTION_UNKNOWN 0 +#define ACTION_SAME 1 +#define ACTION_NEW 2 +#define ACTION_UPGRADE 3 +#define ACTION_ERROR 4 + +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 trust; /* TRUST_* (selects among info[] below) */ + struct { + char *version; /* holds canonical version for fromcwd.cc */ + char *install; /* file name to install */ + int install_size; /* in bytes */ + char *source; /* sources for installed binaries */ + int source_size; /* in bytes */ + } info[NTRUST]; +} Package; + +extern Package *package; +extern int npackages; + +#ifdef __cplusplus +extern "C" { +#endif + +Package *new_package (char *name); +void ini_init (char *string); + +#ifdef __cplusplus +} +#endif diff --git a/inilex.l b/inilex.l new file mode 100644 index 00000000..88a5cf2b --- /dev/null +++ b/inilex.l @@ -0,0 +1,90 @@ +%{ +/* + * 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 + * + */ + +/* 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 + +#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); + +%} + +%option noyywrap + +%% + +\"[^"]*\" { yylval = strdup (yytext+1); + yylval[strlen (yylval)-1] = 0; + return STRING; } + +"setup-timestamp:" return SETUP_TIMESTAMP; +"version:" return VERSION; +"install:" return INSTALL; +"source:" return SOURCE; +"sdesc:" return SDESC; +"ldesc:" return LDESC; + +"[curr]" return T_CURR; +"[test]" return T_TEST; +"[prev]" return T_PREV; + +[a-zA-Z0-9_./-]+ { yylval = strdup (yytext); + return STRING; } + +[ \t\r]+ + +\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; +} diff --git a/iniparse.y b/iniparse.y new file mode 100644 index 00000000..b49ac72f --- /dev/null +++ b/iniparse.y @@ -0,0 +1,107 @@ +%{ +/* + * 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 + * + */ + +/* Parse the setup.ini files. inilex.l provides the tokens for this. */ + +#include + +#include "ini.h" +#include "iniparse.h" + +static Package *cp; +static int trust; +extern unsigned int setup_timestamp; + +#define cpt (cp->info+trust) + +%} + +%token STRING +%token SETUP_TIMESTAMP VERSION INSTALL SOURCE SDESC LDESC +%token T_PREV T_CURR T_TEST + +%% + +whole_file + : setup_headers packages + ; + +setup_headers + : setup_header setup_headers + | /* empty */ + ; + +setup_header + : SETUP_TIMESTAMP STRING '\n' { setup_timestamp = strtoul ($2, 0, 0); } + ; + +packages + : package packages + | /* empty */ + ; + +package + : '@' STRING '\n' { new_package($2); } + lines + | '\n' + ; + +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); } + | T_PREV { trust = TRUST_PREV; } + | T_CURR { trust = TRUST_CURR; } + | T_TEST { trust = TRUST_TEST; } + | /* empty */ + ; + +%% + +Package *package = 0; +int npackages = 0; +static int maxpackages = 0; + +Package * +new_package (char *name) +{ + 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/install.cc b/install.cc new file mode 100644 index 00000000..f6674447 --- /dev/null +++ b/install.cc @@ -0,0 +1,313 @@ +/* + * 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 + * + */ + +/* 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 "win32.h" +#include "commctrl.h" + +#include +#include +#include +#include +#include "zlib/zlib.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 "mount.h" + +static HWND ins_dialog = 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: + ExitProcess(0); + } +} + +static BOOL CALLBACK +dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam) +{ + int i, j; + HWND listbox; + switch (message) + { + case WM_INITDIALOG: + ins_dialog = h; + 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 WINAPI DWORD +dialog (void *) +{ + int rv = 0; + MSG m; + HANDLE ins_dialog = CreateDialog (hinstance, MAKEINTRESOURCE (IDD_INSTATUS), + 0, dialog_proc); + if (ins_dialog == 0) + fatal ("create dialog"); + ShowWindow (ins_dialog, SW_SHOWNORMAL); + UpdateWindow (ins_dialog); + while (GetMessage (&m, 0, 0, 0) > 0) { + TranslateMessage (&m); + DispatchMessage (&m); + } +} + +static DWORD start_tics; + +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 > 0) + { + perc = bytes * 100 / package_bytes; + SendMessage (ins_pprogress, PBM_SETPOS, (WPARAM) perc, 0); + } + + if (total_bytes > 0) + { + perc = (total_bytes_sofar + bytes) * 100 / total_bytes; + SendMessage (ins_iprogress, PBM_SETPOS, (WPARAM) perc, 0); + } + + int df = diskfull (root_dir); + SendMessage (ins_diskfull, PBM_SETPOS, (WPARAM) df, 0); +} + +static void +badrename (char *o, char *n) +{ + char buf[1000]; + char *err = strerror (errno); + if (!err) + err = "(unknown error)"; + note (IDS_ERR_RENAME, o, n, err); +} + +#define pi (package[i].info[package[i].trust]) + +#define LOOP_PACKAGES \ + for (i=0; i + * + */ + +/* 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 +#include "resource.h" +#include "dialog.h" +#include "state.h" +#include "msg.h" +#include "netio.h" +#include "find.h" +#include "mount.h" + +void netio_test (char *); + +int next_dialog; + +HINSTANCE hinstance; + +int WINAPI +WinMain(HINSTANCE h, + HINSTANCE hPrevInstance, + LPSTR command_line, + int cmd_show) +{ + hinstance = h; + + next_dialog = IDD_SOURCE; + + while (next_dialog) + { + switch (next_dialog) + { + case IDD_SOURCE: do_source(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_S_CHOOSE: do_choose(h); break; + case IDD_S_DOWNLOAD: do_download(h); break; + case IDD_S_INSTALL: do_install(h); break; + + default: + next_dialog = 0; + break; + } + } + + return 0; +} diff --git a/memory.c b/memory.c deleted file mode 100644 index e4c8e640..00000000 --- a/memory.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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 Ron Parker - * - */ - -#include -#include -#include -#include "setup.h" - -void * -xmalloc (size_t size) -{ - void *mem = malloc (size); - - if (!mem) - lowmem (); - return mem; -} - -void * -xrealloc (void *orig, size_t newsize) -{ - void *mem = realloc (orig, newsize); - - if (!mem) - lowmem (); - return mem; -} - -char * -xstrdup (const char *arg) -{ - char *str = strdup (arg); - - if (!str) - lowmem (); - return str; -} diff --git a/mkdir.cc b/mkdir.cc new file mode 100644 index 00000000..42d36020 --- /dev/null +++ b/mkdir.cc @@ -0,0 +1,79 @@ +/* + * 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 + * + */ + +/* see mkdir.h */ + +#include "win32.h" + +#include + +#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) + { + if (gse == ERROR_ALREADY_EXISTS) + { + if (DeleteFileA (path)) + { + fprintf(stderr, "warning: deleting \"%s\" so I can make a directory there\n", + 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/strarry.h b/mkdir.h similarity index 53% rename from strarry.h rename to mkdir.h index 0397f361..151edc0b 100644 --- a/strarry.h +++ b/mkdir.h @@ -9,20 +9,13 @@ * A copy of the GNU General Public License can be found at * http://www.gnu.org/ * - * Written by Ron Parker + * Written by DJ Delorie * */ -/* strarry.h: strarry struct */ - -#include -typedef struct strarry -{ - char **array; - size_t count; - size_t index; -} SA; -void sa_init (SA *); /* Initialize the struct. */ -void sa_add (SA *, const char *); /* Add a string to the array. */ -void sa_cleanup (SA *); /* Deallocate all of the memory. */ +/* 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/mount.cc b/mount.cc new file mode 100644 index 00000000..5a0f8ac7 --- /dev/null +++ b/mount.cc @@ -0,0 +1,129 @@ +/* + * 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 + * + */ + +/* The purpose of this file is to hide all the details about accessing + Cygwin's mount table. If the format or location of the mount table + changes, this is the file to change to match it. */ + +#include "win32.h" + +#include +#include "../cygwin/include/cygwin/version.h" +#include "../cygwin/include/sys/mount.h" + +#include "mount.h" +#include "msg.h" +#include "resource.h" +#include "dialog.h" + + +static char * +find2 (HKEY rkey, int *istext) +{ + char buf[1000]; + char *retval = 0; + HKEY key; + DWORD retvallen = 0; + DWORD flags = 0; + DWORD type; + + 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; +} + +char * +find_root_mount (int *istext) +{ + char *rv; + if (rv = find2 (HKEY_CURRENT_USER, istext)) + return rv; + return find2 (HKEY_LOCAL_MACHINE, istext); +} + +void +create_mount (char *posix, char *win32, int istext) +{ + char buf[1000]; + char *retval = 0; + HKEY key; + DWORD retvallen = 0, disposition; + DWORD flags; + + remove_mount (posix); + + sprintf (buf, "Software\\%s\\%s\\%s\\%s", + CYGWIN_INFO_CYGNUS_REGISTRY_NAME, + CYGWIN_INFO_CYGWIN_REGISTRY_NAME, + CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME, + posix); + + if (RegCreateKeyEx (HKEY_CURRENT_USER, buf, 0, "Cygwin", 0, KEY_ALL_ACCESS, + 0, &key, &disposition) != ERROR_SUCCESS) + fatal ("mount"); + + RegSetValueEx (key, "native", 0, REG_SZ, (BYTE *)win32, strlen (win32)+1); + if (istext) + flags = 0; + else + flags = MOUNT_BINARY; + RegSetValueEx (key, "flags", 0, REG_DWORD, (BYTE *)&flags, sizeof (flags)); +} + +static void +remove1 (HKEY rkey, char *posix) +{ + char buf[1000]; + + sprintf (buf, "Software\\%s\\%s\\%s\\%s", + CYGWIN_INFO_CYGNUS_REGISTRY_NAME, + CYGWIN_INFO_CYGWIN_REGISTRY_NAME, + CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME, + posix); + + RegDeleteKey (rkey, buf); +} + +void +remove_mount (char *posix) +{ + remove1 (HKEY_LOCAL_MACHINE, posix); + remove1 (HKEY_CURRENT_USER, posix); +} diff --git a/mount.h b/mount.h new file mode 100644 index 00000000..4c0c7001 --- /dev/null +++ b/mount.h @@ -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 + * + */ + +/* Finds the existing root mount, or returns NULL. istext is set to + nonzero if the existing mount is a text mount, else zero for + binary. */ + +char * find_root_mount (int *istext); + +/* Similar to the mount and umount functions, but simplified */ + +void create_mount (char *posix, char *win32, int istext); +void remove_mount (char *posix); diff --git a/msg.cc b/msg.cc new file mode 100644 index 00000000..8cba9b6b --- /dev/null +++ b/msg.cc @@ -0,0 +1,68 @@ +/* + * 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 + * + */ + +/* The purpose of this file is to centralize all the message + functions. */ + +#include "win32.h" +#include +#include +#include "dialog.h" + +void +msg(char *fmt, ...) +{ + char buf[1000]; + va_list args; + va_start (args, fmt); + vsprintf (buf, fmt, args); + OutputDebugString (buf); +} + +static int mbox (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); + return MessageBox (0, buf, "Cygwin Setup", type); +} + +void +note (int id, ...) +{ + va_list args; + va_start (args, id); + mbox (0, id, args); +} + +void +fatal (int id, ...) +{ + va_list args; + va_start (args, id); + mbox (0, id, args); + ExitProcess (1); +} + +int +yesno (int id, ...) +{ + va_list args; + va_start (args, id); + return mbox (MB_YESNO, id, args); +} diff --git a/msg.h b/msg.h new file mode 100644 index 00000000..ddd37854 --- /dev/null +++ b/msg.h @@ -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 + * + */ + +/* 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/net.cc b/net.cc new file mode 100644 index 00000000..6fb4ee63 --- /dev/null +++ b/net.cc @@ -0,0 +1,152 @@ +/* + * 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 + * + */ + +/* The purpose of this file is to get the network configuration + information from the user. */ + +#include "win32.h" +#include +#include +#include "dialog.h" +#include "resource.h" +#include "state.h" +#include "msg.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; + } + if (pu && (net_proxy_user && !net_proxy_passwd + || !net_proxy_user && net_proxy_passwd)) + e = 0; + EnableWindow (GetDlgItem (h, IDOK), e); + EnableWindow (GetDlgItem (h, IDC_PROXY_HOST), p); + EnableWindow (GetDlgItem (h, IDC_PROXY_PORT), p); + EnableWindow (GetDlgItem (h, IDC_PROXY_USER), pu); + EnableWindow (GetDlgItem (h, IDC_PROXY_PASSWD), pu); +} + +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); + eset (h, IDC_PROXY_USER, net_proxy_user); + eset (h, IDC_PROXY_PASSWD, net_proxy_passwd); + 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); + net_proxy_user = eget (h, IDC_PROXY_USER, net_proxy_user); + net_proxy_passwd = eget (h, IDC_PROXY_PASSWD, net_proxy_passwd); +} + +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: + case IDC_PROXY_USER: + case IDC_PROXY_PASSWD: + 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_SOURCE); + break; + case IDC_SOURCE_NETINST: + case IDC_SOURCE_CWD: + NEXT(IDD_ROOT); + break; + } + break; + + case IDCANCEL: + NEXT(0); + break; + } +} + +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); +} + diff --git a/netio.cc b/netio.cc new file mode 100644 index 00000000..75a8973e --- /dev/null +++ b/netio.cc @@ -0,0 +1,128 @@ +/* + * 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 + * + */ + +/* 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 +#include +#include + +#include "resource.h" +#include "state.h" +#include "msg.h" +#include "netio.h" +#include "nio-file.h" +#include "nio-ie5.h" + +#include "port.h" + +NetIO::NetIO (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 += 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); +} + +NetIO::~NetIO () +{ + if (url) + free (url); + if (proto) + free (proto); + if (host) + free (host); + if (path) + free (path); +} + +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); +#if 0 + else if (net_method == IDC_NET_DIRECT) + rv = new NetIO_Direct (url); + else if (net_method == IDC_NET_PROXY) + rv = new NetIO_Proxy (url); +#endif + + if (!rv->ok ()) + { + delete rv; + return 0; + } + + return rv; +} diff --git a/netio.h b/netio.h new file mode 100644 index 00000000..c8fb49a1 --- /dev/null +++ b/netio.h @@ -0,0 +1,45 @@ +/* + * 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 + * + */ + +/* 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); +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); +}; diff --git a/nio-file.cc b/nio-file.cc new file mode 100644 index 00000000..8bc4624c --- /dev/null +++ b/nio-file.cc @@ -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 + * + */ + +/* 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 "win32.h" +#include +#include +#include +#include +#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/cygcalls.h b/nio-file.h similarity index 70% rename from cygcalls.h rename to nio-file.h index 329e536b..6d2eb928 100644 --- a/cygcalls.h +++ b/nio-file.h @@ -13,10 +13,13 @@ * */ -#include "../cygwin/include/sys/mount.h" -#include "../cygwin/include/mntent.h" +/* see nio-file.cc */ -/* returns zero on success, nonzero on failure */ -int cygcall_load_dll (char *name); - -int cygcall_unload_dll (); +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/nio-ie5.cc b/nio-ie5.cc new file mode 100644 index 00000000..dde8f5d4 --- /dev/null +++ b/nio-ie5.cc @@ -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 + * + */ + +/* 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 */ + +#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) +{ + if (internet == 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; + + if (net_proxy_user && net_proxy_passwd) + { + InternetSetOption (internet, INTERNET_OPTION_PROXY_USERNAME, + net_proxy_user, strlen (net_proxy_user)); + InternetSetOption (internet, INTERNET_OPTION_PROXY_PASSWORD, + net_proxy_passwd, strlen (net_proxy_passwd)); + } + + connection = InternetOpenUrl (internet, url, NULL, 0, flags, 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); + } + else + { + fatal (url); + } + } +} + +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/nio-ie5.h b/nio-ie5.h new file mode 100644 index 00000000..42593335 --- /dev/null +++ b/nio-ie5.h @@ -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 + * + */ + +/* 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); +}; diff --git a/other.cc b/other.cc new file mode 100644 index 00000000..674101ff --- /dev/null +++ b/other.cc @@ -0,0 +1,97 @@ +/* + * 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 + * + */ + +/* This handles the "other URL" option from the mirror site + selection. */ + +#include "win32.h" +#include +#include +#include +#include "dialog.h" +#include "resource.h" +#include "state.h" +#include "msg.h" + + +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); + NEXT(IDD_S_LOAD_INI); + break; + + case IDC_BACK: + save_dialog(h); + NEXT(IDD_SITE); + break; + + case IDCANCEL: + NEXT(0); + break; + } +} + +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); +} + diff --git a/path.c b/path.c deleted file mode 100644 index 183df015..00000000 --- a/path.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * 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 Ron Parker - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "setup.h" -#include "strarry.h" -#include "zlib/zlib.h" - -#if 0 - -static FILE *cygin = NULL, *cygout = NULL; -static HANDLE hcygpath = NULL; - -void -exit_cygpath (void) -{ - if (cygin) - fclose (cygin); - if (cygout) - fclose (cygout); - if (hcygpath) - { - Sleep (0); - if (WaitForSingleObject (hcygpath, 5000) != WAIT_OBJECT_0) - { - TerminateProcess (hcygpath, 0); - WaitForSingleObject (hcygpath, 5000); - } - CloseHandle (hcygpath); - } -} - -static int -cygpath_pipe (void) -{ - int hpipein[2] = {-1, -1}; - int hpipeout[2] = {-1, -1}; - char buffer[256]; - - HANDLE hin, hout; - if (_pipe (hpipein, 256, O_TEXT) == -1) - return 0; - if (_pipe (hpipeout, 256, O_TEXT) == -1) - return 0; - - hin = (HANDLE) _get_osfhandle (hpipein[1]); - hout = (HANDLE) _get_osfhandle (hpipeout[0]); - sprintf (buffer, "cygpath -a -o -f - -c %lx", (unsigned long) _get_osfhandle (hpipeout[1])); - hcygpath = (HANDLE) xcreate_process (0, hout, hin, hin, buffer); - if (!hcygpath) - return 0; - _close (hpipein[1]); - _close (hpipeout[0]); - cygin = fdopen (hpipein[0], "rt"); - cygout = fdopen (hpipeout[1], "wt"); - setbuf (cygout, NULL); - return 1; -} - -char * -pathcvt (char target, const char *path) -{ - char buffer[1024]; - char *retval; - - if (!cygin && !cygpath_pipe ()) - return NULL; /* FIXME - error */ - - fprintf (cygout, "-%c %s\n", target, path); - retval = fgets (buffer, sizeof (buffer), cygin); - if (retval) - { - char *p = strchr (buffer, '\n'); - if (p != NULL) - *p = '\0'; - retval = xstrdup (buffer); - } - - /* If there is an error try using the original style path anyway. */ - return retval ? retval : xstrdup (path); -} - -char * -dtoupath (const char *path) -{ - char *retval = pathcvt ('u', path); - size_t len = strlen (retval); - if (len > 2 && retval[len - 1] == '/') /* Trim the trailing slash - off of a nonroot path. */ - retval[len - 1] = '\0'; - - return retval; -} - -char * -utodpath (const char *path) -{ - char *retval = pathcvt ('w', path); - size_t len = strlen (retval); - if (len > 3 && retval[len - 1] == '\\') /* Trim the trailing slash - off of a nonroot path. */ - retval[len - 1] = '\0'; - - return retval; -} - -#endif /* 0 */ - -char * -pathcat (const char *arg1, const char *arg2) -{ - char path[_MAX_PATH]; - size_t len; - char *s, *d; - - strcpy (path, arg1); - strcat (path, "\\"); - strcat (path, arg2); - - for (s=path; *s; s++) - if (*s == '/') - *s = '\\'; - for (s=d=path; *s; s++) - { - *d++ = *s; - if (*s == '\\') - while (s[1] == '\\') - s++; - } - *d = 0; - - return xstrdup (path); -} diff --git a/pkg.c b/pkg.c deleted file mode 100644 index da72b37f..00000000 --- a/pkg.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * 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 - * - */ - -#include -#include -#include -#include -#include "setup.h" -#include - -#define CYGMAJOR "%%% Cygwin dll major: " -#define CYGMAJOR_LEN (sizeof (CYGMAJOR) - 1) -#define CYGMINOR "%%% Cygwin dll minor: " -#define CYGMINOR_LEN (sizeof (CYGMINOR) - 1) - -pkg global_pkgstuff[1000]; - -void -normalize_version (const char *fn_in, char **prod, char **version) -{ - char *p; - char *fn, *origfn; - char *dot; - static char buf1[1024]; - static char buf2[1024]; - - origfn = buf1; - strcpy (buf1, fn_in); - fn = origfn = buf1; - - if ((p = strstr (fn, ".tar.gz")) != NULL) - *p = '\0'; - else if ((p = strstr (fn, "_tar.gz")) != NULL) - *p = '\0'; - - while (isalpha (*fn)) - fn++; - if (*fn) - *fn++ = '\0'; - - *prod = origfn; - if (!*fn) - { - *version = strcpy (buf2, "0000"); - return; - } - - dot = ""; - buf2[0] = '\0'; - while (*fn) - { - int n; - fn += strspn (fn, "-_.+,"); - if (!*fn) - break; - n = strcspn (fn, "-_.+,"); - sprintf (strchr (buf2, '\0'), "%s%04.*s", dot, n, fn); - fn += n; - dot = "."; - } - - *version = buf2; - return; -} - -static HKEY hkpkg; - -static pkg default_pkgs[] = -{ - {"diff", "0000"}, - {"ash", "0000"}, - {"bash", "0000"}, - {"binutils", "19990818.0001"}, - {"bison", "0000"}, - {"byacc", "0000"}, - {"bzip", "0000"}, - {"clear", "0001.0000"}, - {"dejagnu", "0000"}, - {"expect", "0000"}, - {"fileutils", "0000"}, - {"findutils", "0000"}, - {"flex", "0000"}, - {"gawk", "0000"}, - {"gcc", "0002.0095.0002.0001"}, - {"gdb", "20000415"}, - {"gperf", "0000"}, - {"grep", "0000"}, - {"groff", "0001.011a.0001"}, - {"gzip", "0000"}, - {"less", "0000"}, - {"m", "0000"}, - {"make", "0000"}, - {"man", "0001.005g.0001"}, - {"patch", "0000"}, - {"sed", "0000"}, - {"shellutils", "0000"}, - {"tar", "0000"}, - {"tcltk", "0000"}, - {"termcap", "0000"}, - {"texinfo", "0000"}, - {"textutils", "0000"}, - {"time", "0000"}, - {NULL, NULL} -}; - -pkg * -use_default_pkgs (pkg *stuff) -{ - pkg *def, *stf; - int sawend; - def = default_pkgs; - - sawend = 0; - for (stf = stuff, def = default_pkgs; def->name != NULL; stf++) - { - if (sawend || !stf->name) - { - stf->name = xstrdup (def->name); - stf->version = xstrdup (def->version); - def++; - sawend = 1; - } - (void) write_pkg (NULL, stf->name, stf->version); - } - stf->name = NULL; - stf->version = NULL; - return stuff; -} - -pkg * -find_pkg (pkg *stuff, char *name) -{ - int i; - - for (i = 0; stuff[i].name; i++) - if (stricmp (stuff[i].name, name) == 0) - return stuff + i; - - return NULL; -} - -const char * -check_for_installed (const char *root, pkg *stuff) -{ - char *cygwin = pathcat (root, "bin\\cygwin1.dll"); - FILE *fp = fopen (cygwin, "rb"); - char *buf, *bufend; - struct _stat st; - char *major, *minor; - pkg *pkg; - static char buf1[256]; - - xfree (cygwin); - - if (fp == NULL) - return NULL; - - if (_fstat (fileno (fp), &st)) - goto err; - - buf = xmalloc (st.st_size); - if (!buf) - goto err; - - if (fread (buf, st.st_size, 1, fp) <= 0) - goto err; - - fclose (fp); - - bufend = buf + st.st_size; - major = minor = NULL; - while (buf < bufend) - if ((buf = memchr (buf, '%', bufend - buf)) == NULL) - return 0; - else if (strncmp (buf, CYGMAJOR, CYGMAJOR_LEN) == 0) - major = buf += CYGMAJOR_LEN; - else if (strncmp (buf, CYGMINOR, CYGMINOR_LEN) != 0) - buf++; - else - { - minor = buf + CYGMINOR_LEN; - break; - } - - if (!minor) - return NULL; - - sprintf (buf1, "%04d.%04d.%04d", atoi (major) / 1000, atoi (major) % 1000, atoi (minor)); - - pkg = find_pkg (stuff, "cygwin"); - if (pkg) - xfree (pkg->version); - else - { - pkg = stuff; - stuff[1].name = stuff[1].version = NULL; - } - - pkg->name = xstrdup ("cygwin"); - pkg->version = xstrdup (buf1); - - sprintf (buf1, "%d.%d.%d", atoi (major) / 1000, atoi (major) % 1000, atoi (minor)); - - return buf1; - -err: - fclose (fp); - return NULL; -} - -#define REGWHERE "SOFTWARE\\Cygnus Solutions\\Cygwin\\Installed Components" - -pkg * -init_pkgs (const char *root, int use_current_user) -{ - LONG res; - DWORD what; - char *p, empty[] = ""; - char buf[4096]; - DWORD ty, sz; - DWORD nc = 0; - - sprintf (buf, "%s\\%s", REGWHERE, root); - for (p = buf + sizeof (REGWHERE); (p = strchr (p, '\\')) != NULL; ) - *p = '/'; - - res = RegCreateKeyEx (use_current_user ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, buf, - 0, empty, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkpkg, &what); - - if (res != ERROR_SUCCESS) - return NULL; - - for (nc = 0, sz = sizeof (buf); - RegEnumValue (hkpkg, nc, buf, &sz, NULL, &ty, NULL, NULL) == ERROR_SUCCESS; - nc++, sz = sizeof (buf)) - { - DWORD sz = sizeof (buf); - global_pkgstuff[nc].name = xstrdup (buf); - - if (RegQueryValueEx (hkpkg, global_pkgstuff[nc].name, NULL, - &ty, buf, &sz) == ERROR_SUCCESS) - global_pkgstuff[nc].version = xstrdup (buf); - else - global_pkgstuff[nc].version = xstrdup (""); - } - - global_pkgstuff[nc].version = global_pkgstuff[nc].name = NULL; - return global_pkgstuff; -} - -int -write_pkg (pkg *pkg, char *name, char *version) -{ - if (pkg != NULL && stricmp (pkg->version, version) >= 0) - return 0; - - RegSetValueEx (hkpkg, name, 0, REG_SZ, version, strlen (version) + 1); - return 1; -} - -int -newer_pkg (pkg *pkg, char *version) -{ - if (pkg != NULL && stricmp (pkg->version, version) >= 0) - return 0; - return 1; -} - -void -close_pkgs () -{ - RegCloseKey (hkpkg); -} - -#ifdef check -int -main (int argc, char **argv) -{ - pkg *stuff = init_pkgs (); - - while (*++argv) - { - char *stub, *ver; - pkg *pkg; - normalize_version (*argv, &stub, &ver); - printf ("%s = %s, %s\n", *argv, stub, ver); - if ((pkg = find_pkg (stuff, stub)) != NULL) - printf ("found pkg %s = %s\n", pkg->name, pkg->version); - printf ("write_pkg returns %d\n", write_pkg (pkg, stub, ver)); - } - exit (0); -} -#endif diff --git a/port.h b/port.h new file mode 100644 index 00000000..c2c019ad --- /dev/null +++ b/port.h @@ -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 + * + */ + +/* 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/res.rc b/res.rc new file mode 100644 index 00000000..24c324fd --- /dev/null +++ b/res.rc @@ -0,0 +1,272 @@ +/* + * 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 + * + */ + + +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_SOURCE DIALOG DISCARDABLE 0, 0, 215, 95 +STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Cygwin Setup" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "Next -->",IDOK,100,75,45,15,WS_DISABLED + PUSHBUTTON "Cancel",IDCANCEL,165,75,45,15 + PUSHBUTTON "<-- Back",IDC_BACK,55,75,45,15,WS_DISABLED + ICON IDI_CYGWIN,-1,5,5,20,20 + CONTROL "Download from Internet to Current Directory", + IDC_SOURCE_DOWNLOAD,"Button",BS_AUTORADIOBUTTON,55,15, + 152,10 + CONTROL "Install from Internet",IDC_SOURCE_NETINST,"Button", + BS_AUTORADIOBUTTON,55,30,75,10 + CONTROL "Install from Current Directory",IDC_SOURCE_CWD,"Button", + BS_AUTORADIOBUTTON,55,45,104,10 +END + +IDD_ROOT DIALOG DISCARDABLE 0, 0, 215, 95 +STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Cygwin Setup" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "Next -->",IDOK,100,75,45,15 + PUSHBUTTON "Cancel",IDCANCEL,165,75,45,15 + EDITTEXT IDC_ROOT_DIR,55,25,127,12,ES_AUTOHSCROLL + LTEXT "Select install root directory",IDC_STATIC,55,15,135,11 + PUSHBUTTON "<-- Back",IDC_BACK,55,75,45,15 + ICON IDI_CYGWIN,IDC_STATIC,5,5,20,20 + PUSHBUTTON "Browse...",IDC_ROOT_BROWSE,55,40,45,15 + CONTROL "Text Mounts",IDC_ROOT_TEXT,"Button",BS_AUTORADIOBUTTON, + 120,45,55,10 + CONTROL "Binary Mounts",IDC_ROOT_BINARY,"Button", + BS_AUTORADIOBUTTON,120,55,61,10 +END + +IDD_SITE DIALOG DISCARDABLE 0, 0, 215, 95 +STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Cygwin Setup" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "Next -->",IDOK,100,75,45,15 + PUSHBUTTON "Cancel",IDCANCEL,165,75,45,15 + LTEXT "Select Download Site",IDC_STATIC,55,5,135,11 + PUSHBUTTON "<-- Back",IDC_BACK,55,75,45,15 + ICON IDI_CYGWIN,IDC_STATIC,5,5,20,20 + LISTBOX IDC_URL_LIST,55,20,155,51,LBS_NOINTEGRALHEIGHT | + WS_VSCROLL | WS_HSCROLL | WS_TABSTOP +END + +IDD_OTHER_URL DIALOG DISCARDABLE 0, 0, 215, 95 +STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Cygwin Setup" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "Next -->",IDOK,100,75,45,15 + PUSHBUTTON "Cancel",IDCANCEL,165,75,45,15 + EDITTEXT IDC_OTHER_URL,55,25,127,12,ES_AUTOHSCROLL + LTEXT "Select URL to download from",IDC_STATIC,55,15,135,11 + PUSHBUTTON "<-- Back",IDC_BACK,55,75,45,15 + ICON IDI_CYGWIN,IDC_STATIC,5,5,20,20 +END + +IDD_NET DIALOG DISCARDABLE 0, 0, 215, 141 +STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Cygwin Setup" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "Next -->",IDOK,100,120,45,15,WS_DISABLED + PUSHBUTTON "Cancel",IDCANCEL,165,120,45,15 + ICON IDI_CYGWIN,IDC_STATIC,5,5,20,20 + CONTROL "Use IE5 Settings",IDC_NET_IE5,"Button", + BS_AUTORADIOBUTTON,55,15,69,10 + CONTROL "Direct Connection",IDC_NET_DIRECT,"Button", + BS_AUTORADIOBUTTON | WS_DISABLED,55,30,73,10 + CONTROL "Use HTTP/FTP Proxy:",IDC_NET_PROXY,"Button", + BS_AUTORADIOBUTTON | WS_DISABLED,55,45,88,10 + EDITTEXT IDC_PROXY_HOST,65,60,80,12,ES_AUTOHSCROLL | WS_DISABLED + LTEXT "Proxy",IDC_STATIC,10,60,50,15,SS_CENTERIMAGE, + WS_EX_RIGHT + LTEXT "Port",IDC_STATIC,155,60,20,15,SS_CENTERIMAGE, + WS_EX_RIGHT + EDITTEXT IDC_PROXY_PORT,180,60,30,12,ES_AUTOHSCROLL | WS_DISABLED + EDITTEXT IDC_PROXY_USER,65,80,145,12,ES_AUTOHSCROLL | WS_DISABLED + LTEXT "Optional User ID",IDC_STATIC,5,80,55,15,SS_CENTERIMAGE, + WS_EX_RIGHT + EDITTEXT IDC_PROXY_PASSWD,65,95,145,12,ES_AUTOHSCROLL | + WS_DISABLED + LTEXT "Password",IDC_STATIC,10,95,50,15,SS_CENTERIMAGE, + WS_EX_RIGHT + PUSHBUTTON "<-- Back",IDC_BACK,55,120,45,15 +END + +IDD_DLSTATUS DIALOG DISCARDABLE 0, 0, 215, 95 +STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +CAPTION "Cygwin Setup" +FONT 8, "MS Sans Serif" +BEGIN + PUSHBUTTON "Cancel",IDCANCEL,165,75,45,15 + LTEXT "Downloading...",IDC_STATIC,55,15,135,8 + LTEXT "(URL)",IDC_DLS_URL,55,30,150,8 + LTEXT "(RATE)",IDC_DLS_RATE,55,45,155,8 + CONTROL "Progress1",IDC_DLS_PROGRESS,"msctls_progress32", + PBS_SMOOTH | WS_BORDER,55,60,155,10 + ICON IDI_CYGWIN,IDC_STATIC,5,5,20,20 +END + +IDD_INSTATUS DIALOG DISCARDABLE 0, 0, 215, 95 +STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +CAPTION "Cygwin Setup" +FONT 8, "MS Sans Serif" +BEGIN + PUSHBUTTON "Cancel",IDCANCEL,165,75,45,15 + LTEXT "Installing...",IDC_STATIC,55,5,135,8 + LTEXT "(PKG)",IDC_INS_PKG,55,15,150,8 + LTEXT "(FILE)",IDC_INS_FILE,55,25,155,8 + CONTROL "Progress1",IDC_INS_DISKFULL,"msctls_progress32", + PBS_SMOOTH | WS_BORDER,55,60,155,10 + ICON IDI_CYGWIN,IDC_STATIC,5,5,20,20 + CONTROL "Progress1",IDC_INS_IPROGRESS,"msctls_progress32", + PBS_SMOOTH | WS_BORDER,55,50,155,10 + CONTROL "Progress1",IDC_INS_PPROGRESS,"msctls_progress32", + PBS_SMOOTH | WS_BORDER,55,40,155,10 + RTEXT "Package",IDC_STATIC,5,40,45,8 + RTEXT "Total",IDC_STATIC,10,50,40,8 + RTEXT "Disk",IDC_STATIC,5,60,45,8 +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_CYGWIN ICON DISCARDABLE "cygwin.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_NET, DIALOG + BEGIN + BOTTOMMARGIN, 95 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE DISCARDABLE +BEGIN + IDS_ROOT_SLASH "Warning: we recommend you do NOT use the root of your hard drive as the cygwin root. Proceed anyway?" + IDS_ROOT_SPACE "You should not choose a root path that include spaces in directory names. Proceed anyway?" + IDS_MIRROR_LST "http://sourceware.cygnus.com/cygwin/mirrors.lst" + IDS_DIALOG_FAILED "Unable to create Dialog Box" + IDS_CYGWIN_FUNC_MISSING "Error: unable to find function `%s' in %s" + IDS_DOWNLOAD_SHORT "Download error: %s too short (%d, wanted %d)" + IDS_ERR_OPEN_WRITE "Can't open %s for writing: %s" + IDS_SETUPINI_MISSING "Unable to get setup.ini from %s" + IDS_OLD_SETUPINI "This setup.ini is older than the one you used last time you installed cygwin. Proceed anyway?" + IDS_ERR_RENAME "Cab't rename %s to %s: %s" + IDS_NOTHING_INSTALLED "Nothing needed to be installed" + IDS_INSTALL_COMPLETE "Installation Complete" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_ERR_OPEN_READ "Can't open %s for reading: %s" + IDS_ROOT_ABSOLUTE "The install directory must be absolute, with both a drive letter and leading slash, like C:\\Cygwin" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/resource.h b/resource.h index 2d76c7e6..f29815d7 100644 --- a/resource.h +++ b/resource.h @@ -9,22 +9,79 @@ * A copy of the GNU General Public License can be found at * http://www.gnu.org/ * - * Written by Ron Parker + * Written by DJ Delorie * */ //{{NO_DEPENDENCIES}} // Microsoft Developer Studio generated include file. -// Used by setupres.rc +// Used by res.rc // +#define IDS_ROOT_SLASH 1 +#define IDS_ROOT_SPACE 2 +#define IDS_CWD_NONEMPTY 3 +#define IDS_MIRROR_LST 6 +#define IDS_DIALOG_FAILED 7 +#define IDS_CYGWIN_FUNC_MISSING 8 +#define IDS_DOWNLOAD_SHORT 9 +#define IDS_ERR_OPEN_WRITE 10 +#define IDS_SETUPINI_MISSING 11 +#define IDS_OLD_SETUPINI 12 +#define IDS_ERR_RENAME 13 +#define IDS_NOTHING_INSTALLED 14 +#define IDS_INSTALL_COMPLETE 15 +#define IDS_ERR_OPEN_READ 16 +#define IDS_ROOT_ABSOLUTE 17 +#define IDD_ROOT 101 +#define IDD_SOURCE 102 +#define IDD_OTHER_URL 103 +#define IDD_SITE 104 +#define IDD_NET 105 +#define IDD_DLSTATUS 106 +#define IDD_S_LOAD_INI 107 +#define IDD_S_FROM_CWD 108 +#define IDD_S_CHOOSE 109 +#define IDD_S_DOWNLOAD 110 +#define IDD_S_INSTALL 111 +#define IDD_INSTATUS 112 +#define IDI_CYGWIN 200 +#define IDC_SOURCE_DOWNLOAD 1000 +#define IDC_SOURCE_NETINST 1001 +#define IDC_SOURCE_CWD 1002 +#define IDC_ROOT_DIR 1003 +#define IDC_ROOT_BROWSE 1004 +#define IDC_ROOT_TEXT 1005 +#define IDC_ROOT_BINARY 1006 +#define IDC_URL_LIST 1007 +#define IDC_SITE_NEXT 1008 +#define IDC_BACK 1009 +#define IDC_OTHER_URL 1010 +#define IDC_NET_IE5 1011 +#define IDC_NET_DIRECT 1012 +#define IDC_NET_PROXY 1013 +#define IDC_PROXY_HOST 1014 +#define IDC_PROXY_PORT 1015 +#define IDC_PROXY_USER 1016 +#define IDC_PROXY_PASSWD 1017 +#define IDC_DLS_PROGRESS 1019 +#define IDC_DLS_URL 1020 +#define IDC_DLS_RATE 1021 +#define IDC_INS_PKG 1022 +#define IDC_INS_FILE 1023 +#define IDC_INS_DISKFULL 1024 +#define IDC_INS_IPROGRESS 1025 +#define IDC_INS_PPROGRESS 1026 +#define IDC_STATIC -1 // Next default values for new objects -// +// #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 102 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NO_MFC 1 +#define _APS_3D_CONTROLS 1 +#define _APS_NEXT_RESOURCE_VALUE 113 +#define _APS_NEXT_COMMAND_VALUE 40003 +#define _APS_NEXT_CONTROL_VALUE 1027 #define _APS_NEXT_SYMED_VALUE 101 -#endif /* */ -#endif /* */ +#endif +#endif diff --git a/root.cc b/root.cc new file mode 100644 index 00000000..24874c43 --- /dev/null +++ b/root.cc @@ -0,0 +1,214 @@ +/* + * 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 + * + */ + +/* 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 +#include +#include +#include + +#include "dialog.h" +#include "resource.h" +#include "state.h" +#include "msg.h" +#include "mount.h" + +static int rb[] = { IDC_ROOT_TEXT, IDC_ROOT_BINARY, 0 }; + +static void +check_if_enable_next (HWND h) +{ + EnableWindow (GetDlgItem (h, IDOK), root_text && root_dir); +} + +static void +load_dialog (HWND h) +{ + rbset (h, rb, root_text); + eset (h, IDC_ROOT_DIR, root_dir); + check_if_enable_next (h); +} + +static void +save_dialog (HWND h) +{ + root_text = rbget (h, rb); + root_dir = eget (h, IDC_ROOT_DIR, root_dir); +} + +static void +read_mount_table () +{ + int istext; + root_dir = find_root_mount (&istext); + if (root_dir) + { + if (istext) + root_text = IDC_ROOT_TEXT; + else + root_text = IDC_ROOT_BINARY; + } +} + +static int CALLBACK +browse_cb (HWND h, UINT msg, LPARAM lp, LPARAM data) +{ + switch (msg) + { + case BFFM_INITIALIZED: + 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 +directory_has_spaces () +{ + if (strchr (root_dir, ' ')) + 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_TEXT: + case IDC_ROOT_BINARY: + 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 (directory_has_spaces ()) + if (IDNO == yesno (IDS_ROOT_SPACE)) + break; + + 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_SOURCE); + break; + + case IDCANCEL: + NEXT(0); + break; + } +} + +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; + if (!root_dir) + read_mount_table(); + rv = DialogBox (h, MAKEINTRESOURCE (IDD_ROOT), 0, dialog_proc); + if (rv == -1) + fatal (IDS_DIALOG_FAILED); +} + diff --git a/setup.c b/setup.c deleted file mode 100644 index 4f3aa087..00000000 --- a/setup.c +++ /dev/null @@ -1,1910 +0,0 @@ -/* - * 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 Ron Parker - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "setup.h" -#include "strarry.h" -#include "zlib/zlib.h" -#include "cygcalls.h" - -#define MIRRORFILE "http://sourceware.cygnus.com/cygwin/mirrors.html" - -#define CYGNUS_KEY "Software\\Cygnus Solutions" -#define DEF_ROOT "C:\\cygwin" -#define DOWNLOAD_SUBDIR "latest/" -#define SCREEN_LINES 23 -#define SCREEN_COLS 80 -#define COMMAND9X "command.com /E:4096 /c " - -#ifndef NFILE_LIST -#define NFILE_LIST 10000 -#endif - -#ifndef NFILE_SLOP -#define NFILE_SLOP 20 -#endif - -char *wd = NULL; -static char *tarpgm; - -static char *tar_map[8]; - -static int downloaddir (SA *installme, const char *url); - -static SA files = {NULL, 0, 0}; -static FILE *logfp = NULL; -static HANDLE devnull = NULL; -static HINTERNET session = NULL; -static SA deleteme = {NULL, 0, 0}; -static pkg *pkgstuff; -static int updating = 0; -static int download_only = 0; -static SA installme = {NULL, 0, 0}; -static HANDLE hMainThread; -static char *root; -static int mount_text = 0; - -static void -cleanup (void) -{ - int i, j; -#if 0 - extern void exit_cygpath (void); - exit_cygpath (); -#endif - cygcall_unload_dll (); - for (i = deleteme.count; --i >= 0; ) - for (j = 0; !DeleteFile (deleteme.array[i]) && j < 20; j++) - Sleep (1); - sa_cleanup (&deleteme); -} - -static void -cleanup_on_signal (int sig __attribute__ ((unused))) -{ - chdir (wd); - _chdrive (toupper (*wd) - 'A' + 1); - fprintf (stderr, "\n*Exit*\r\n"); - SuspendThread (hMainThread); - cleanup (); - /* I have no idea why this is necessary but, without this, code - seems to continue executing in the main thread even after - the ExitProcess??? */ - TerminateThread (hMainThread, 1); - ExitProcess (1); -} - -#define TARGZ_SIZE (sizeof ("tar.gz") - 1) -static char * -istargz (char *fn) -{ - size_t len = strlen (fn); - static char stem[16384]; - - if (len > sizeof (".tar.gz") && - stricmp (fn + (len -= TARGZ_SIZE), "tar.gz") == 0) - { - char *p; - memcpy (stem, fn, len); - p = stem + len; - if (strchr ("._-", p[-1])) - p--; - *p = '\0'; - return stem; - } - - return NULL; -} - -void -warning (const char *fmt, ...) -{ - va_list args; - va_start (args, fmt); - vfprintf (stderr, fmt, args); - if (logfp) - vfprintf (logfp, fmt, args); -} - -static int -create_shortcut (const char *target, const char *shortcut) -{ - HRESULT hres; - IShellLink *sl; - char *path, *args; - - if (!SUCCEEDED (CoInitialize (NULL))) - return 0; - - hres = - CoCreateInstance (&CLSID_ShellLink, NULL, - CLSCTX_INPROC_SERVER, &IID_IShellLink, (LPVOID *) & sl); - if (SUCCEEDED (hres)) - { - IPersistFile *pf; - int quoted = 0; - char *c; - - /* Get the command only. */ - path = xstrdup (target); - for (c = path; quoted || (*c != ' ' && *c); ++c) - { - if (*c == '\"') - quoted = !quoted; - } - if (*c) - { - *c = '\0'; - args = c + 1; - } - else - args = ""; - - sl->lpVtbl->SetPath (sl, path); - sl->lpVtbl->SetArguments (sl, args); - xfree (path); - - hres = sl->lpVtbl->QueryInterface (sl, &IID_IPersistFile, (void **) &pf); - - if (SUCCEEDED (hres)) - { - WCHAR widepath[_MAX_PATH]; - - // Ensure that the string is Unicode. - MultiByteToWideChar (CP_ACP, 0, shortcut, -1, widepath, MAX_PATH); - - // Save the link by calling IPersistFile::Save. - hres = pf->lpVtbl->Save (pf, widepath, TRUE); - pf->lpVtbl->Release (pf); - } - sl->lpVtbl->Release (sl); - } - - CoUninitialize (); - - return SUCCEEDED (hres); -} - -BOOL CALLBACK -output_file (HMODULE h __attribute__ ((unused)), - LPCTSTR type __attribute__ ((unused)), - LPTSTR name, LONG lparam __attribute__ ((unused))) -{ - HRSRC rsrc; - HGLOBAL res; - char *data; - FILE *out = NULL; - BOOL retval = FALSE; - - size_t bytes_needed; - if ((rsrc = FindResource (NULL, name, "FILE")) - && (res = LoadResource (NULL, rsrc)) - && (data = (char *) LockResource (res)) && (out = fopen (strlwr (name), "w+b"))) - { - gzFile gzf; - char *buffer; - size_t bytes = SizeofResource (NULL, rsrc); - - if (bytes != fwrite (data, 1, bytes, out)) - warning ("Unable to write %s: %s", name, _strerror ("")); - - bytes_needed = *(int *) ((char *) data + bytes - sizeof (int)); - buffer = (char *) xmalloc (bytes_needed); - - rewind (out); - gzf = gzdopen (_dup (fileno (out)), "rb"); - if (gzf && (size_t) gzread (gzf, buffer, bytes_needed) == bytes_needed) - { - if (fseek (out, 0, SEEK_SET) - || fwrite (buffer, 1, bytes_needed, out) != bytes_needed) - { - warning ("Unable to write decompressed file to %s: %s", - name, _strerror ("")); - } - else - retval = TRUE; - } - else - { - int errnum; - const char *msg = gzerror (gzf, &errnum); - warning ("bytes_needed = %d, ", bytes_needed); - warning ("Unable to decompress %s: Error #%d, %s\n", name, - errnum, msg); - } - xfree (buffer); - if (gzf) - gzclose (gzf); - fclose (out); - sa_add (&deleteme, name); - } - else - { - warning ("Unable to write %s: %s", name, _strerror ("")); - } - - return retval; -} - -/* copied from zlib/gzio.c */ -static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ - -/* gzip flag byte */ -#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ -#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ -#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ -#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ -#define COMMENT 0x10 /* bit 4 set: file comment present */ -#define RESERVED 0xE0 /* bits 5..7: reserved */ - -static char * -skip_gzip_header(char *data) -{ - int method; /* method byte */ - int flags; /* flags byte */ - uInt len; - int c; - - c = *data++; /* magic */ - c = *data++; - method = *data++; - flags = *data++; - - /* Discard time, xflags and OS code: */ - data += 6; - - if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ - len = (uInt)*data++; - len += ((uInt)*data++)<<8; - data += len; - } - if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ - while (*data++ != 0) ; - } - if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ - while (*data++ != 0) ; - } - if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ - data += 2; - } - return data; -} - -static void -save_resource_as_file (char *resource_name, char *file_name) -{ - z_stream z; - size_t size; - HRSRC rsrc; - HGLOBAL res; - char *data; - char buffer[65536]; - int zr, i, j; - FILE *out; - - rsrc = FindResource (NULL, resource_name, "FILE"); - if (!rsrc) - { - fprintf (stderr, "error: cannot find file %s in resources\n", resource_name); - exit (1); - } - res = LoadResource (NULL, rsrc); - - out = fopen (file_name, "wb"); - if (!out) - { - fprintf (stderr, "error: unable to write to %s\n", file_name); - perror ("the error was"); - exit (1); - } - - memset (&z, 0, sizeof(z)); - data = (char *) LockResource (res); - z.next_in = skip_gzip_header (data); - z.avail_in = SizeofResource (NULL, rsrc) - ((char *)z.next_in-data); - z.zalloc = Z_NULL; - z.zfree = Z_NULL; - z.data_type = Z_BINARY; - - inflateInit2 (&z, -MAX_WBITS); - - zr = Z_OK; - while (zr == Z_OK) - { - z.next_out = buffer; - z.avail_out = sizeof (buffer); - - switch (zr = inflate (&z, 0)) - { - case Z_OK: - case Z_STREAM_END: - i = sizeof (buffer) - z.avail_out; - j = fwrite (buffer, 1, i, out); - if (j < i) - { - fprintf (stderr, "error: out of disk space writing to %s\n", file_name); - exit (1); - } - break; - - default: - fprintf (stderr, "error decompressing %s: %s\n", resource_name, z.msg); - exit (1); - } - } - - inflateEnd (&z); - fclose (out); -} - -static void -xumount (const char *mountexedir, const char *unixpath) -{ - umount (unixpath); -} - -extern FILE * _tar_vfile; -extern int _tar_verbose; - -static int -tarx (const char *dir, const char *fn) -{ - char *path, *dpath; - char buffer0[2049]; - char *buffer = buffer0 + 1; - int hpipe[2]; - HANDLE hin; - HANDLE hproc; - FILE *fp; - unsigned filehere; - char *pkgname, *pkgversion; - pkg *pkg; - - if (strnicmp (fn, "cygwin-20000301", sizeof ("cygwin-20000301") - 1) == 0) - normalize_version ("cygwin-1.1.0.tar.gz", &pkgname, &pkgversion); - else - normalize_version (fn, &pkgname, &pkgversion); - pkg = find_pkg (pkgstuff, pkgname); - if (!newer_pkg (pkg, pkgversion)) - { - warning ("Skipped extraction of %s since newer version is installed\n", fn); - return 1; - } - - printf ("Installing %s\n", fn); - - dpath = pathcat (dir, fn); - _tar_vfile = logfp; - _tar_verbose = 2; - return !tar_auto (dpath, tar_map); -} - -static int -refmatches (SA *installme, char *ref, char *refend) -{ - unsigned i; - char *p, *q; - char filebuf[4096]; - if (!installme->count) - return 1; - - for (p = ref; (q = strchr (p, '/')) != refend; p = q + 1) - continue; - - strcpy (filebuf, p); - strchr (filebuf, '\0')[-1] = '\0'; - for (i = 0; i < installme->count; i++) - if (stricmp (installme->array[i], filebuf) == 0) - return 1; - - return 0; -} - -static int -filematches (SA *installme, char *fn) -{ - unsigned i; - - if (!installme->count) - return 1; - - for (i = 0; i < installme->count; i++) - if (strnicmp (installme->array[i], fn, strlen (installme->array[i])) == 0) - return 1; - - return 0; -} - -static int -recurse_dirs (SA *installme, const char *dir) -{ - int err = 0; - int retval = 0; - - char *pattern = pathcat (dir, "*"); - if (pattern) - { - WIN32_FIND_DATA find_data; - HANDLE handle; - - handle = FindFirstFile (pattern, &find_data); - if (handle != INVALID_HANDLE_VALUE) - { - /* Recurse through all subdirectories */ - do - { - if (strcmp (find_data.cFileName, ".") == 0 - || strcmp (find_data.cFileName, "..") == 0 - || !filematches (installme, find_data.cFileName)) - continue; - - if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY - /* && strlen(find_data.cFileName) */ ) - { - char *subdir = pathcat (dir, find_data.cFileName); - if (subdir) - { - if (!recurse_dirs (installme, subdir)) - { - xfree (subdir); - err = 1; - break; - } - - xfree (subdir); - } - else - lowmem (); - } - } - while (FindNextFile (handle, &find_data) && !err); - FindClose (handle); - - /* Look for .tar.gz files */ - if (!err) - { - xfree (pattern); - pattern = pathcat (dir, "*.gz"); - handle = FindFirstFile (pattern, &find_data); - if (handle != INVALID_HANDLE_VALUE) - { - int err = 0; - - do - { - char *bat; - /* Skip source archives and meta-directories */ - if (strstr (find_data.cFileName, "-src") != 0 - || strcmp (find_data.cFileName, ".") == 0 - || strcmp (find_data.cFileName, "..") == 0 - || !(bat = istargz (find_data.cFileName)) - || !filematches (installme, find_data.cFileName)) - { - continue; - } - - if (!tarx (dir, find_data.cFileName)) - { - err = 1; - break; - } -#ifdef USE_BATFILE - strcat (bat, ".bat"); - if (access (bat, 00)) - { - sprintf (strchr (bat, '\0'), " \"%s\"", root); - (void) xcreate_process (1, NULL, NULL, NULL, bat); - } -#endif - } - while (FindNextFile (handle, &find_data)); - FindClose (handle); - } - if (!err) - retval = 1; - } - } - - xfree (pattern); - } - else - lowmem (); - - return retval; -} - -static void -setpath (const char *element) -{ - char *buffer = xmalloc (strlen (element) + 7); - - sprintf (buffer, "PATH=%s", element); - putenv (buffer); - - xfree (buffer); -} - -static char * -prompt (const char *text, const char *def) -{ - char buffer[_MAX_PATH]; - - printf ((def ? "%s? [%s] " : "%s? "), text, def); - fflush (stdout); - fgets (buffer, sizeof (buffer), stdin); - buffer[strcspn (buffer, "\r\n")] = '\0'; - - /* Duplicate the entered value or the default if nothing was entered. */ - return xstrdup (strlen (buffer) ? buffer : def ? def : ""); -} - -static int -optionprompt (const char *text, SA * options) -{ - size_t n, c, ncols, response = -1; - char buf[5]; - size_t base; - int maxwidth=0, skip, percol; - int screen_lines = SCREEN_LINES; - - for (n=0; ncount; n++) - { - int sl = strlen(options->array[n]); - if (maxwidth < sl) - maxwidth = sl; - } - - ncols = SCREEN_COLS / (maxwidth + 5); - skip = (options->count + ncols - 1) / ncols; - percol = SCREEN_COLS / ncols; - - if (options->count < ncols * screen_lines) - screen_lines = (options->count+ncols-1)/ncols; - - base = 0; - - puts (text); - - while (1) - { - char *repeat, *enter; - - for (n = 0; n < screen_lines; n++) - { - if (n + base >= options->count) - break; - for (c = 0; c < ncols; c++) - { - unsigned i = n + base + c * screen_lines; - if (i < options->count) - printf ("%2d. %-*s", i + 1, percol - 5, options->array[i]); - } - printf ("\n"); - } - - repeat = enter = ""; - if (skip > screen_lines) - { - if (base) - repeat = " or `R' to repeat the list"; - if (base + screen_lines * ncols < options->count) - enter = " or [Enter] for more options"; - } - - printf ("Select an option from 1-%d%s%s: ", options->count, repeat, enter); - if (!fgets (buf, sizeof (buf), stdin)) - { - /* This can only mean end-of-file, user has gone away */ - exit(1); - } - - response = atoi(buf); - if (response >= 1 && response <= options->count) - return response - 1; - - if (buf[0] == 'c' || buf[0] == 'C' || buf[0] == '\r' || buf[0] == '\n') - { - if (base + screen_lines * ncols < options->count) - base += screen_lines * ncols; - } - if (buf[0] == 'r' || buf[0] == 'R') - base = 0; - - } -} - -static int -geturl (const char *url, const char *file, int verbose) -{ - DWORD type, size; - int authenticated = 0; - int retval = 0; - static HINTERNET connect; - int tries = 20; - int is_ftp = strnicmp (url, "ftp", 3) == 0; - static int saw_first_ftp = 0; - char connect_buffer[1024]; - - if (saw_first_ftp) - verbose = 0; - else if (verbose) - { - const char *hosthere, *hostend; - int n; - - hosthere = strstr (url, "//"); - if (!hosthere) - hosthere = url; /* huh? */ - else - hosthere += 2; - - hostend = strchr (hosthere + 1, '/'); - if (!hostend) - hostend = strchr (hosthere + 1, '\0'); - n = hostend - hosthere; - sprintf (connect_buffer, "Connecting to %.*s...", n, hosthere); - fputs (connect_buffer, stdout); - fflush (stdout); - if (is_ftp) - saw_first_ftp = 1; - } - - for (tries = 1; tries <= 40; tries++) - { - DWORD flags = INTERNET_FLAG_DONT_CACHE | - INTERNET_FLAG_KEEP_CONNECTION | - INTERNET_FLAG_PRAGMA_NOCACHE | - INTERNET_FLAG_RELOAD; - - if (is_ftp) - flags |= INTERNET_FLAG_EXISTING_CONNECT | - INTERNET_FLAG_PASSIVE; - - connect = InternetOpenUrl (session, url, NULL, 0, flags, 0); - if (connect) - break; - if (!verbose || tries == 1) - /* nothing */; - else if (tries > 2) - printf ("\r%s(try %d) \b\b", connect_buffer, tries); - else - printf ("\r%s(try %d)", connect_buffer, tries); - } - - if (!connect) - { - puts ("\nCouldn't connect to ftp site."); fflush (stdout); - winerror (); - } - else - { - if (verbose) - { - if (tries > 1) - printf ("\r%s \r", connect_buffer); - printf ("Done.\n"); fflush (stdout); - } - while (!authenticated) - { - size = sizeof (type); - if (!InternetQueryOption - (connect, INTERNET_OPTION_HANDLE_TYPE, &type, &size)) - { - winerror (); - return 0; - } - else - switch (type) - { - case INTERNET_HANDLE_TYPE_HTTP_REQUEST: - case INTERNET_HANDLE_TYPE_CONNECT_HTTP: - size = sizeof (DWORD); - if (!HttpQueryInfo - (connect, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, - &type, &size, NULL)) - { - winerror (); - return 0; - } - else if (type == HTTP_STATUS_PROXY_AUTH_REQ) - { - DWORD len; - - if (!InternetQueryDataAvailable (connect, &len, 0, 0)) - { - winerror (); - return 0; - } - else - { - char *user, *password; - - /* Have to read any pending data, WININET peculiarity. */ - char *buffer = xmalloc (len); - do - { - InternetReadFile (connect, buffer, len, &size); - } - while (size); - xfree (buffer); - - puts ("Proxy authentication is required.\n"); - - user = prompt ("Proxy username", NULL); - if (!InternetSetOption - (connect, INTERNET_OPTION_PROXY_USERNAME, user, - strlen (user))) - { - xfree (user); - winerror (); - return 0; - } - else - { - xfree (user); - password = prompt ("Proxy password", NULL); - if (!InternetSetOption - (connect, INTERNET_OPTION_PROXY_PASSWORD, - password, - strlen (password)) - || !HttpSendRequest (connect, NULL, 0, NULL, 0)) - { - xfree (password); - winerror (); - return 0; - } - xfree (password); - } - } - } - else if (type != HTTP_STATUS_OK) - { - warning ("Error retrieving \"%s\".\n", url); - return 0; - } - else - authenticated = 1; - break; - - default: - authenticated = 1; - break; - } - - /* Now that authentication is complete read the file. */ - if (!InternetQueryDataAvailable (connect, &size, 0, 0)) - winerror (); - else - { - char status[50]; - static char *bs[50] = {0}; - int total = 0; - char *buffer; - FILE *out; - DWORD start_time, cur_time, delta_time; - - if (bs[0] == 0) - memset(bs, '\b', sizeof(bs)); - - if (size < 1024) /* optimize */ - size = 1024; - buffer = xmalloc (size); - - out = fopen (file, "wb"); - if (!out) - warning ("Unable to open \"%s\" for output: %s\n", file, - _strerror ("")); - else - { - status[0] = 0; - start_time = GetTickCount (); - for (;;) - { - DWORD readbytes; - - if (!InternetReadFile (connect, buffer, size, &readbytes)) - winerror (); - else if (!readbytes) - { - retval = 1; - break; - } - else if (fwrite (buffer, 1, readbytes, out) != readbytes) - { - warning ("Error writing \"%s\": %s\n", file, - _strerror ("")); - break; - } - total += readbytes; - delta_time = GetTickCount () - start_time; - - if (delta_time > 5000) - { - int kbps = (total+500) / delta_time; - sprintf(status, " %dk %dk/s", total / 1024, kbps); - printf("%s%.*s", status, strlen(status), bs); - } - } - if (status[0]) - printf("%*c%.*s", strlen(status), ' ', strlen(status), bs); - fclose (out); - } - xfree (buffer); - } - - InternetCloseHandle (connect); - connect = NULL; - } - } - - return retval; -} - -static char * -findhref (char *buffer, char *date __attribute__ ((unused)), - size_t *filesize) -{ - char *ref = NULL; - char *anchor = NULL; - char *p; - int eatspace; - char *q; - char digits[20]; - char *diglast = digits + sizeof (digits) - 1; - int len; - - p = buffer; - while ((p = strchr (p, '<')) != NULL) - { - char *q = p; - char ch = *++p; - - if (tolower (ch) != 'a') - continue; - - ch = *++p; - if (!isspace (ch)) - continue; - - for (++p; isspace (*p); p++) - continue; - - if (strnicmp (p, "href=", 5) == 0) - { - ref = p; - anchor = q; - } - } - - if (!ref) - return NULL; - - ref += ref[5] == '"' ? 6 : 5; - - len = strcspn (ref, "\" >"); - - ref[len] = '\0'; - if (!filesize) - goto out; - - *filesize = 0; - - if (anchor == buffer || !isspace (anchor[-1])) - goto out; - - eatspace = 1; - *diglast = '\0'; - for (p = anchor, q = diglast; --p >= buffer; ) - if (!isspace (*p)) - { - eatspace = 0; - if (isdigit (*p)) - *--q = *p; - } - else if (!eatspace) - break; - - if (q < diglast) - *filesize = atoi (q); - -out: - if (!*ref) - return NULL; - /* This effectively disallows using a ';' in a file name. Hopefully, - this will not be an issue. */ - if ((p = strrchr (ref, ';')) != NULL) - *p = '\0'; - return *ref ? ref : NULL; -} - -static int -needfile (const char *filename, char *date __attribute__ ((unused)), - size_t filesize) -{ - struct _stat st; - - if (!filesize || _stat (filename, &st)) - return 1; /* file doesn't exist or is somehow not accessible */ - return (size_t) st.st_size != filesize; -} - -static int -processdirlisting (SA *installme, const char *urlbase, const char *file) -{ - int retval = 0; - char buffer[4096]; - static enum {UNKNOWN, ALWAYS, NEVER} download_when = {UNKNOWN}; - size_t urllen = strlen (urlbase); - - FILE *in = fopen (file, "rt"); - - while (fgets (buffer, sizeof (buffer), in)) - { - size_t filesize; - char filedate[80]; - char *ref = findhref (buffer[0] ? buffer : buffer + 1, filedate, &filesize); - char url[256]; - DWORD urlspace = sizeof (url); - char *refend; - - if (!ref || strnicmp (ref, "http:", 5) == 0) - continue; - - if (!InternetCombineUrl - (urlbase, ref, url, &urlspace, - ICU_BROWSER_MODE | ICU_ENCODE_SPACES_ONLY | ICU_NO_META)) - { - warning ("Unable to download from %s", ref); - winerror (); - } - else if (strlen (url) == urllen || strnicmp (urlbase, url, urllen) != 0 - || strstr (url, "/.") || strstr (url, "./")) - continue; - - refend = ref + strlen (ref) - 1; - if (*refend == '/') - { - if (refmatches (installme, ref, refend)) - retval += downloaddir (installme, url); - } - else if (istargz (url) && !strstr (url, "-src")) - { - int download = 0; - char *filename = strrchr (url, '/') + 1; - char *pkgname, *pkgversion; - pkg *pkg; - - if (!filematches (installme, filename)) - continue; - - retval++; - - if (!download_only) - { - if (strnicmp (filename, "cygwin-20000301", sizeof ("cygwin-20000301") - 1) == 0) - normalize_version ("cygwin-1.1.0.tar.gz", &pkgname, &pkgversion); - else - normalize_version (filename, &pkgname, &pkgversion); - pkg = find_pkg (pkgstuff, pkgname); - - if (!newer_pkg (pkg, pkgversion)) - { - warning ("Skipped download of %s\n", filename); - continue; - } - } - - if (download_when == ALWAYS || needfile (filename, filedate, filesize)) - download = 1; - else - { - char text[_MAX_PATH]; - char *answer; - - if (download_when == NEVER) - answer = xstrdup ("N"); - else - { - sprintf (text, "Replace %s from the Internet (ynAN)", filename); - answer = prompt (text, "y"); - } - - if (answer) - { - switch (*answer) - { - case 'a': - case 'A': - download_when = ALWAYS; - /* purposely fall through */ - case 'y': - case 'Y': - download = 1; - break; - case 'N': - download_when = NEVER; - warning ("Skipped download of %s\n", filename); - case 'n': - default: - download = 0; - } - xfree (answer); - } - } - - if (!download) - continue; - - for (;;) /* file retrieval loop */ - { - int res; - warning ("Downloading: %s...", filename); - fflush (stdout); - res = geturl (url, filename, 0); - if ((res && !filesize) || !needfile (filename, filedate, filesize)) - warning ("Done.\n"); - else - { - for (;;) /* prompt loop */ - { - char a; - char *answer; - if (!res) - warning ("Download failed.\n"); - else - fprintf (logfp, "Downloaded file size does not match (%d).\n", - filesize); - answer = prompt (res ? "Downloaded file size does not match (Abort, Retry, Fail)" : - "Download failed (Abort, Retry, Fail)", "R"); - a = toupper (*answer); - xfree (answer); - switch (a) - { - case 'R': - break; /* try it again */ - case 'A': - exit (1); /* abort program */ - case 'F': - warning ("Deleting %s.\n", filename); - _unlink (filename); - goto noget; /* Keep trying to download the rest */ - default: - continue; /* erroneous response */ - } - - break; /* from prompt loop */ - } - } - - noget: - break; /* Leave from file retrieval for loop. - Either we successfully downloaded the file - or the user said don't bother. */ - } - } - } - - fflush (stdout); - fclose (in); - - return retval; -} - -static char * -tmpfilename () -{ - char *rv = _tempnam (NULL, "su"); - sa_add (&deleteme, rv); - return rv; -} - -static int -downloaddir (SA *installme, const char *url) -{ - int retval = 0; - char *file = tmpfilename (); - - if (geturl (url, file, 1)) - retval = processdirlisting (installme, url, file); - _unlink (file); - xfree (file); - - return retval; -} - -static HINTERNET -opensession () -{ - return InternetOpen ("Cygwin Setup", INTERNET_OPEN_TYPE_PRECONFIG, NULL, - NULL, 0); -} - -static int -downloadfrom (SA *installme, const char *url) -{ - int retval = 0; - char *file = tmpfilename (); - - if (geturl (url, file, 1)) - retval = processdirlisting (installme, url, file); - _unlink (file); - - xfree (file); - - return retval; -} - -static int -reverse_sort (const void *arg1, const void *arg2) -{ - return -strcmp (*(char **) arg1, *(char **) arg2); -} - -static int -create_uninstall (const char *folder, const char *shellscut, - const char *shortcut) -{ - int retval = 0; - - warning ("Creating the uninstall file..."); - fflush (stdout); - if (files.array) - { - size_t n; - FILE *uninst; - char cwd[MAX_PATH]; - char *uninstfile; - - getcwd (cwd, sizeof (cwd)); - uninstfile = pathcat (cwd, "uninst.bat"); - uninst = fopen (uninstfile, "wt"); - - if (uninst) - { - struct _stat st; - - files.array[++files.index] = pathcat (cwd, "bin\\cygwin.bat"); - files.count = files.index + 1; - qsort (files.array, files.count, sizeof (char *), reverse_sort); - - fprintf (uninst, - "@echo off\n" "%c:\n" "cd \"%s\"\n", *cwd, cwd); - fprintf (uninst, "bin\\regtool remove '/HKLM/SOFTWARE/Cygnus Solutions/cygwin/Installed Components'\n"); - for (n = 0; n < files.count; ++n) - { - char *dpath; - - if (n && !strcmp (files.array[n], files.array[n - 1])) - continue; - - dpath = files.array[n]; - - if (_stat (dpath, &st) == 0 && st.st_mode & _S_IFDIR) - fprintf (uninst, "rmdir \"%s\"\n", dpath); - else - { - if (access (dpath, 6) != 0) - fprintf (uninst, "attrib -r \"%s\"\n", dpath); - fprintf (uninst, "del \"%s\"\n", dpath); - } - } - fprintf (uninst, - "del \"%s\"\n" - "del \"%s\"\n" - "rmdir \"%s\"\n" - "del %s\n", shortcut, shellscut, - folder, uninstfile); - fclose (uninst); - - create_shortcut (uninstfile, shortcut); - } - sa_cleanup (&files); - retval = 1; - } - - warning ("Done.\n"); - return retval; -} - -/* Writes the startup batch file. */ -static int -do_start_menu (void) -{ - FILE *batch; - char *batch_name = pathcat (root, "bin\\cygwin.bat"); - int retval = 0; - - /* Create the batch file for the start menu. */ - if (batch_name) - { - batch = fopen (batch_name, "wt"); - if (batch) - { - LPITEMIDLIST progfiles; - char pfilespath[_MAX_PATH]; - char *folder; - char *bindir = pathcat (root, "bin"); - char *locbindir = pathcat (root, "usr\\local\\bin"); - - fprintf (batch, - "@echo off\n" - "SET MAKE_MODE=unix\n" - "SET PATH=%s;%s;%%PATH%%\n" - "bash\n", bindir, locbindir); - fclose (batch); - xfree (bindir); - xfree (locbindir); - - /* Create a shortcut to the batch file */ - SHGetSpecialFolderLocation (NULL, CSIDL_PROGRAMS, &progfiles); - SHGetPathFromIDList (progfiles, pfilespath); - - folder = pathcat (pfilespath, "Cygnus Solutions"); - if (folder) - { - char *shortcut; - mkdir (folder); /* Ignore the result, it may exist. */ - - shortcut = pathcat (folder, "Cygwin 1.1.0.lnk"); - if (shortcut) - { - char *cmdline; - OSVERSIONINFO verinfo; - verinfo.dwOSVersionInfoSize = sizeof (verinfo); - - /* If we are running Win9x, build a command line. */ - GetVersionEx (&verinfo); - if (verinfo.dwPlatformId == VER_PLATFORM_WIN32_NT) - cmdline = xstrdup (batch_name); - else - { - char *pccmd; - char windir[MAX_PATH]; - GetWindowsDirectory (windir, sizeof (windir)); - - pccmd = pathcat (windir, COMMAND9X); - cmdline = - xmalloc (strlen (pccmd) + strlen (batch_name) + 1); - strcat (strcpy (cmdline, pccmd), batch_name); - xfree (pccmd); - } - - if (create_shortcut (cmdline, shortcut) - && (!updating || installme.count)) - { - char *uninstscut = - pathcat (folder, "Uninstall Cygwin 1.1.0.lnk"); - if (uninstscut) - { - if (create_uninstall (folder, shortcut, uninstscut)) - retval = 1; - xfree (uninstscut); - } - } - xfree (cmdline); - xfree (shortcut); - } - xfree (folder); - } - } - xfree (batch_name); - } - return retval; -} - -static char * -getdownloadsource () -{ - char *retval = NULL; - char *filename = tmpfilename (); - - /* Initialize session one time and one time only */ - session = opensession (); - - if (!session) - { - winerror (); - exit (1); - } - - if (!geturl (MIRRORFILE, filename, 1)) - fputs ("Unable to retrieve the list of cygwin mirrors.\n", stderr); - else - { - FILE *in = fopen (filename, "rt"); - - if (!in) - warning ("Unable to open %s for input.\n", filename); - else - { - size_t option; - int ready4urls = 0; - char buf[256]; - SA urls, names; /* These must stay sync'd. */ - - sa_init (&urls); - sa_init (&names); - - while (fgets (buf, sizeof (buf), in)) - { - if (!ready4urls) - { - if (strstr (buf, "Mirror Sites:")) - ready4urls = 1; - } - else - { - char *ref = findhref (buf, NULL, NULL); - - if (ref) - { - size_t len = strlen (ref); - - if (ref[len - 1] == '/') - { - char *name; - char *url = xmalloc (len + 13); - - strcat (strcpy (url, ref), DOWNLOAD_SUBDIR); - sa_add (&urls, url); - - /* Get just the sites name. */ - name = strstr (url, "//"); - if (name) - name += 2; - else - name = url; - *strchr (name, '/') = '\0'; - sa_add (&names, name); - - xfree (url); - } - } - } - } - - fclose (in); - sa_add (&urls, "Other"); - sa_add (&names, "Other"); - option = - optionprompt ("Select a download location close to you:", &names); - if (option == urls.count - 1) - retval = prompt ("Download url", NULL); - else - retval = xstrdup (urls.array[option]); - - sa_cleanup (&urls); - sa_cleanup (&names); - } - } - _unlink (filename); - - return retval; -} - -/* Basically a mkdir -p /somedir function. */ -static void -mkdirp (const char *dir) -{ - if (mkdir (dir) == -1 && errno != EEXIST) - { - char *parent = strdup (dir); - char *slash = strrchr (parent, '\\'); - - if (slash) - { - *slash = '\0'; - mkdirp (parent); - } - - xfree (parent); - - mkdir (dir); - } -} - -/* This routine assumes that the cwd is the root directory. */ -static int -mkmount (const char *dospath, const char *unixpath) -{ - char *mountd, *fulldospath; - - assert (root != NULL); - - if (dospath[0]) - { - /* Make sure the mount point exists. */ - mountd = pathcat (root, unixpath); - mkdirp (mountd); - xfree (mountd); - fulldospath = pathcat (root, dospath); - } - else - { - fulldospath = xstrdup (root); - } - - /* Make sure the target path exists. */ - mkdirp (fulldospath); - - umount (unixpath); - mount (fulldospath, unixpath, mount_text ? 0 : MOUNT_BINARY); - - xfree (fulldospath); -} - -static pkg * -get_pkg_stuff (int updating) -{ - const char *ver, *ans; - pkg *pkgstuff = init_pkgs (root, 0); - - if (!updating || !pkgstuff) - { - extern pkg global_pkgstuff[]; - (void) check_for_installed (root, global_pkgstuff); - return global_pkgstuff; - } - - ver = check_for_installed (root, pkgstuff); - - if (pkgstuff->name != NULL) - return pkgstuff; - - if (!ver || stricmp (ver, "1.1.0") != 0) - return pkgstuff; - - ans = prompt ( - "\nHmm. You seem to have a previous cygwin version installed but there is no\n" - "package version information in the registry. This is probably due to the fact\n" - "that previous versions of setup.exe did not update this information.\n" - "Should I update the registry with default information now", "y"); - puts (""); - if (toupper (*ans) != 'Y') - { - warning ("Not writing default package information to the registry.\n"); - puts (""); - return pkgstuff; - } - - warning ("Writing default package information to the registry.\n"); - puts (""); - return use_default_pkgs (pkgstuff); -} - -static void -do_tar_map (int i, char *from, char *root, char *to) -{ - char *t; - tar_map[i] = from; - i++; - tar_map[i] = (char *) xmalloc (strlen(root) + strlen(to) + 3); - t = tar_map[i]; - strcpy (t, root); - if (t[strlen(t)-1] == '/' && to[0] == '/') - to ++; - strcat (t, to); -} - -static int -current_directory_not_empty () -{ - WIN32_FIND_DATA find_data; - HANDLE h = FindFirstFile ("*", &find_data); - int count = 0; - if (h != INVALID_HANDLE_VALUE) - do - { - DWORD fa = GetFileAttributes (find_data.cFileName); - int len = strlen (find_data.cFileName); - if (strcmp (find_data.cFileName, ".") == 0 - || strcmp (find_data.cFileName, "..") == 0) - continue; - if (fa & FILE_ATTRIBUTE_DIRECTORY) - count ++; - if (strcmp (find_data.cFileName+len-7, ".tar.gz") == 0) - count ++; - } while (FindNextFile (h, &find_data)); - FindClose (h); - return count; -} - -static void -usage () -{ - printf ("\n"); - printf ("Usage: setup [-f] [-u] [-d] [package ...]\n"); - printf ("-f\tforce re-install\n"); - printf ("-u\tupdate old packages\n"); - printf ("-d\tdownload to current directory only - no install\n"); - printf ("`package' lists packages to install/update\n"); - printf ("\n"); - exit (1); -} - - -static char rev[] = "$Revision$ "; - -int -main (int argc, char **argv) -{ - int retval = 1; /* Default to error code */ - clock_t start; - char *logpath = NULL; - char *revn, *p; - int fd = _open ("nul", _O_WRONLY | _O_BINARY); - struct mntent *m; - char *defroot; - char *update; - char *tmp; - int done; - HKEY cu = NULL, lm = NULL; - - while (argc > 1 && argv[1][0] == '-') - { - if (stricmp (argv[1], "-f") == 0) - updating = 0; - else if (stricmp (argv[1], "-u") == 0) - updating = 1; - else if (stricmp (argv[1], "-d") == 0) - download_only = 1; - else - usage (); - argc--; - argv++; - } - - sa_init (&installme); - while (argc > 1) - { - sa_add (&installme, argv[1]); - argc--; - argv++; - } - - devnull = (HANDLE) _get_osfhandle (fd); - - setbuf (stdout, NULL); - SetEnvironmentVariable ("CYGWIN", NULL); - revn = strchr (rev, ':'); - if (!revn || (p = strchr (revn + 2, ' ')) == NULL) - revn = ""; - else - { - revn--; - memcpy (revn, " (v", 3); - *p = ')'; - p[1] = '\0'; - } - - printf ( "\n\n" - "This is the Cygwin setup utility%s,\n" - "built on " __DATE__ " " __TIME__ ". Run \"setup -h\" for command-line help.\n\n", revn); - - if (!download_only) printf ( -"Use this program to install the latest version of the Cygwin Utilities\n" -"from the Internet.\n\n" -"Alternatively, if you already have already downloaded the appropriate files\n" -"to the current directory (and subdirectories below it), this program can use\n" -"those as the basis for your installation.\n\n" -"If you are installing from the Internet, please run this program in an empty\n" -"temporary directory.\n\n"); - - start = clock (); - sa_init (&deleteme); - - wd = _getcwd (NULL, 0); - - save_resource_as_file ("cygwin1.dll", "setup-cygwin1.dll"); - cygcall_load_dll ("setup-cygwin1.dll"); - sa_add (&deleteme, "setup-cygwin1.dll"); - - setmntent (0,0); - defroot = 0; - while (m = getmntent (0)) - { -#if 0 - printf ("mnt fs=%s dir=%s type=%s opts=%s freq=%d pass=%d\n", - m->mnt_fsname, m->mnt_dir, m->mnt_type, m->mnt_opts, m->mnt_freq, m->mnt_passno); -#endif - if (strcmp (m->mnt_dir, "/") == 0) - { - defroot = xstrdup (m->mnt_fsname); - if (strstr (m->mnt_opts, "text")) - mount_text = 1; - } - } - if (!defroot) - defroot = xstrdup (DEF_ROOT); - - - setpath (wd); - tmp = xmalloc (sizeof ("TMP=") + strlen (wd)); - sprintf (tmp, "TMP=%s", wd); - _putenv (tmp); - - logpath = pathcat (wd, "setup.log"); - tarpgm = pathcat (wd, "tar.exe"); - - if (logpath) - logfp = fopen (logpath, "wt"); - - if (logfp == NULL) - { - fprintf (stderr, "Unable to open log file '%s' for writing - %s\n", - logpath, _strerror ("")); - exit (1); - } - - /* Begin prompting user for setup requirements. */ - printf ("Press to accept the default values.\n"); - - if (updating) - { - printf("\nNote: You have chosen to update an existing installation.\n"); - printf("You should accept the defaults for the root mount and mode.\n"); - } - - DuplicateHandle (GetCurrentProcess (), GetCurrentThread (), - GetCurrentProcess (), &hMainThread, 0, 0, - DUPLICATE_SAME_ACCESS); - atexit (cleanup); - signal (SIGINT, cleanup_on_signal); - - if (!download_only) - { - /* Get the root directory and warn the user if there are any spaces in - the path. */ - for (done = 0; !done;) - { - root = prompt ("Root directory", defroot); - /* convert to windows format */ - for (p=root; *p; p++) - if (*p == '/') - *p = '\\'; - if (strcmpi (root, wd) == 0) - { - printf ("Please do not use the current directory as the root directory.\n" - "You should run setup.exe from a temporary directory.\n"); - continue; - } - if (strchr (root, ' ')) - { - char *temp; - temp = - prompt - ("Using spaces in the root directory path may cause problems." - " Continue anyway", "no"); - if (toupper (*temp) == 'Y') - done = 1; - xfree (temp); - continue; - } - if (!isalpha (root[0]) || root[1] != ':' || (root[2] != '\\')) - { - printf ("The root directory should include a drive letter and leading\n"); - printf ("slash, like c:\\cygwin or g:\\local\\unix\n"); - continue; - } - if (root[3] == '\0' || root[3] == '\\') - { - char *yesno, y; - printf ("We strongly recommend that you DO NOT install Cygwin in the root\n"); - printf ("of a partition. This install will put many files in the root if\n"); - printf ("you choose this option.\n"); - yesno = prompt ("Are you sure you want to install there", "N"); - y = yesno[0]; - free (yesno); - if (y != 'y' && y != 'Y') - continue; - } - done = 1; - } - xfree (defroot); - - done = 0; - while (!done) - { - char *resp = prompt ("Mount mode (T)ext, (B)inary, or (H)elp", - mount_text ? "Text" : "Binary"); - switch (resp[0]) - { - case 't': - case 'T': - mount_text = 1; - done = 1; - break; - case 'b': - case 'B': - mount_text = 0; - done = 1; - break; - case 'h': - case 'H': - case '?': - printf ("\n"); - printf ("With text mounts, files are converted to/from DOS text format\n"); - printf ("This is more compatible with MS programs, but some unix programs\n"); - printf ("may break when they see text files as input.\n"); - printf ("With binary mounts, files are saved without carriage returns, which\n"); - printf ("is best for other cygwin programs but may break MS programs\n"); - printf ("\n"); - break; - } - } - } - - Sleep (0); - - if (download_only) - update = "i"; - else - { - pkgstuff = get_pkg_stuff (updating); - - update = - prompt ("Install from the current directory (d) or from the Internet (i)", "i"); - } - - if (toupper (*update) == 'I') - { - char *dir; - - if (!download_only && current_directory_not_empty ()) - { - char *yns, yn; - printf ("\nThe current directory is not empty. You should run setup in\n"); - printf ("an empty temporary directory when installing from the\n"); - printf ("Internet. *Any* tar.gz file found in this directory *or* any\n"); - printf ("subdirectory will be installed, not just files setup downloads.\n\n"); - yns = prompt ("Use this directory anyway? [yn]", "n"); - yn = yns[0]; - xfree (yns); - if (yn != 'y' && yn != 'Y') - exit (1); - } - - dir = getdownloadsource (); - - if (!dir) - { - fprintf (stderr, "Couldn't connect to download site.\n"); - exit (1); - } - - if (!downloadfrom (&installme, dir)) - { - warning ("Error: No files found to download."); - if (!installme.count) - warning(" Choose another mirror site?\n"); - else - warning ("\n"); - goto out; - } - InternetCloseHandle (session); - xfree (dir); - } - xfree (update); - - if (! download_only) - { - - /* Create the root directory. */ - mkdirp (root); /* Ignore any return value since it may - already exist. */ - - /* Make the root directory the current directory so that recurse_dirs - will * extract the packages into the correct path. */ - if (chdir (root) == -1) - { - warning ("Unable to make \"%s\" the current directory: %s\n", - root, _strerror ("")); - } - else - { - FILE *fp; - - _chdrive (toupper (*root) - 'A' + 1); - - do_tar_map (0, "usr/bin/", root, "/bin/"); - do_tar_map (2, "usr/lib/", root, "/lib/"); - do_tar_map (4, "", root, "/"); - tar_map[6] = tar_map[7] = 0; - - - mkdirp ("var\\run"); - /* Create /var/run/utmp */ - fp = fopen ("var\\run\\utmp", "wb"); - if (fp) - fclose (fp); - - files.count = NFILE_LIST; - files.array = calloc (sizeof (char *), NFILE_LIST + NFILE_SLOP); - files.index = -1; - - /* Extract all of the packages that are stored with setup or in - subdirectories of its location */ - if (recurse_dirs (&installme, wd)) - { - /* bash expects a /tmp */ - char *tmpdir = pathcat (root, "tmp"); - - if (tmpdir && mkdir (tmpdir) == 0) - files.array[++files.index] = tmpdir; - - files.array[++files.index] = pathcat (root, "usr\\local"); - files.array[++files.index] = pathcat (root, "usr\\local\\bin"); - files.array[++files.index] = pathcat (root, "usr\\local\\lib"); - files.array[++files.index] = pathcat (root, "usr\\local\\etc"); - mkdirp (files.array[files.index]); - mkdir (files.array[files.index - 1]); - mkdir (files.array[files.index - 2]); - - if (do_start_menu ()) - retval = 0; /* Everything worked return - successful code */ - - warning ("Creating mount points..."); - umount ("/usr"); - umount ("/var"); - umount ("/lib"); - umount ("/bin"); - umount ("/etc"); - - /* Make /bin point to /usr/bin and /lib point to /usr/lib. */ - mkmount ("", "/"); - mkmount ("bin", "/usr/bin"); - mkmount ("lib", "/usr/lib"); - - } - } - } - - xfree (root); - - chdir (wd); - _chdrive (toupper (*wd) - 'A' + 1); - -out: - puts (""); - warning ("Installation took %.0f seconds.\n", - (double) (clock () - start) / CLK_TCK); - - if (logpath) - { - fclose (logfp); - xfree (logpath); - } - - return retval; -} diff --git a/setup.dsp b/setup.dsp deleted file mode 100644 index 648b26fd..00000000 --- a/setup.dsp +++ /dev/null @@ -1,130 +0,0 @@ -# Microsoft Developer Studio Project File - Name="setup" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=setup - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "setup.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "setup.mak" CFG="setup - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "setup - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "setup - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "setup - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "." -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wininet.lib /nologo /subsystem:console /machine:I386 - -!ELSEIF "$(CFG)" == "setup - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "g:\cygwin-net-485" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wininet.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "setup - Win32 Release" -# Name "setup - Win32 Debug" -# Begin Source File - -SOURCE=.\cygpath.exe.gz -# End Source File -# Begin Source File - -SOURCE=.\cygwin1.dll.gz -# End Source File -# Begin Source File - -SOURCE=.\error.c -# End Source File -# Begin Source File - -SOURCE=.\gzip.exe.gz -# End Source File -# Begin Source File - -SOURCE=.\memory.c -# End Source File -# Begin Source File - -SOURCE=.\setup.c -# End Source File -# Begin Source File - -SOURCE=.\setup.h -# End Source File -# Begin Source File - -SOURCE=.\setupres.rc -# End Source File -# Begin Source File - -SOURCE=.\strarry.c -# End Source File -# Begin Source File - -SOURCE=.\strarry.h -# End Source File -# Begin Source File - -SOURCE=.\tar.exe.gz -# End Source File -# End Target -# End Project diff --git a/setup.dsw b/setup.dsw deleted file mode 100644 index 7757b833..00000000 --- a/setup.dsw +++ /dev/null @@ -1,44 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "setup"=.\setup.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name zlib - End Project Dependency -}}} - -############################################################################### - -Project: "zlib"=.\zlib.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/setup.h b/setup.h deleted file mode 100644 index 00eadf28..00000000 --- a/setup.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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 Ron Parker - * - */ - -#include - -/* Package versioning stuff */ - -typedef struct -{ - char *name; - char *version; -} pkg; - -pkg *init_pkgs (const char * root, int); -pkg * find_pkg (pkg *stuff, char *name); -int write_pkg (pkg *pkg, char *name, char *version); -int newer_pkg (pkg *pkg, char *version); -void normalize_version (const char *fn, char **prod, char **version); -void close_pkgs (void); - -pkg *use_default_pkgs (pkg *stuff); -const char * check_for_installed (const char *root, pkg *stuff); - -/* Routines in error.c. */ -void lowmem (); /* Report low memory and exit the - application. */ -void winerror (); /* Report errors from GetLastError. */ - -/* Routines in memory.c. */ -void *xmalloc (size_t); /* Like malloc, but exit on error. */ -void *xrealloc (void *, size_t); /* Like realloc, but exit on error. */ -char *xstrdup (const char *); /* Like strdup, but exit on error. */ - -#define xfree(ptr) free(ptr) - -char *pathcat (const char *arg1, const char *arg2); -char *pathcvt (char target, const char *path); -char *dtoupath (const char *path); -char *utodpath (const char *path); - -int xsystem (const char *cmd); -DWORD xcreate_process (int wait, HANDLE in, HANDLE out, HANDLE err, const char *cmd); diff --git a/setupres.rc b/setupres.rc deleted file mode 100644 index de3209d7..00000000 --- a/setupres.rc +++ /dev/null @@ -1,5 +0,0 @@ -cygwin1.dll FILE DISCARDABLE "cygwin1.dll.gz" -tar.exe FILE DISCARDABLE "tar.exe.gz" -gzip.exe FILE DISCARDABLE "gzip.exe.gz" -cygpath.exe FILE DISCARDABLE "cygpath.exe.gz" -mount.exe FILE DISCARDABLE "mount.exe.gz" diff --git a/site.cc b/site.cc new file mode 100644 index 00000000..84c53d69 --- /dev/null +++ b/site.cc @@ -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 + * + */ + +/* 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 +#include +#include + +#include "dialog.h" +#include "resource.h" +#include "state.h" +#include "geturl.h" +#include "msg.h" + +#include "port.h" + +#define NO_IDX (-1) +#define OTHER_IDX (-2) +static char **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]; + } +} + +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 + NEXT(IDD_S_LOAD_INI); + break; + + case IDC_BACK: + save_dialog(h); + NEXT(IDD_NET); + break; + + case IDCANCEL: + NEXT(0); + break; + } +} + +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]; i++) + { + j = SendMessage (listbox, LB_ADDSTRING, 0, (LPARAM)site_list[i]); + 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 +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; + + int nmirrors = 2; /* null plus account for possibly missing NL */ + for (bol=mirrors; *bol; bol++) + if (*bol == '\n') + nmirrors ++; + + site_list = (char **) malloc (nmirrors * sizeof (char *)); + 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] > ' ') + { + site_list[nmirrors] = _strdup (bol); + char *semi = strchr (site_list[nmirrors], ';'); + if (semi) + *semi = 0; + nmirrors++; + } + } + site_list[nmirrors] = 0; + + return 0; +} + +void +do_site (HINSTANCE h) +{ + int rv = 0; + + if (site_list == 0) + if (get_site_list (h)) + { + NEXT(0); + return; + } + + rv = DialogBox (h, MAKEINTRESOURCE (IDD_SITE), 0, dialog_proc); + if (rv == -1) + fatal (IDS_DIALOG_FAILED); +} + diff --git a/source.cc b/source.cc new file mode 100644 index 00000000..3f9a5338 --- /dev/null +++ b/source.cc @@ -0,0 +1,111 @@ +/* + * 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 + * + */ + +/* 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 +#include "dialog.h" +#include "resource.h" +#include "state.h" +#include "msg.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) +{ + int i; + rbset (h, rb, source); + check_if_enable_next (h); +} + +static void +save_dialog (HWND h) +{ + int i; + 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); + switch (source) + { + case IDC_SOURCE_DOWNLOAD: + NEXT(IDD_NET); + break; + case IDC_SOURCE_NETINST: + case IDC_SOURCE_CWD: + NEXT(IDD_ROOT); + break; + } + break; + + case IDC_BACK: + save_dialog(h); + NEXT(0); + break; + + case IDCANCEL: + NEXT(0); + break; + } +} + +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); +} + diff --git a/state.cc b/state.cc new file mode 100644 index 00000000..23502c22 --- /dev/null +++ b/state.cc @@ -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 + * + */ + +/* All we do here is instantiate the extern'd variables from state.h */ + +#define extern +#include "state.h" diff --git a/state.h b/state.h new file mode 100644 index 00000000..c3344b5d --- /dev/null +++ b/state.h @@ -0,0 +1,37 @@ +/* + * 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 + * + */ + +/* 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 * root_dir; +extern int root_text; + +extern int net_method; +extern char * net_proxy_host; +extern int net_proxy_port; +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/strarry.c b/strarry.c deleted file mode 100644 index 9bc1c664..00000000 --- a/strarry.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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 Ron Parker - * - */ - -/* strarry.c: implementation of the strarry struct routines. */ -#include -#include -#include "setup.h" -#include "strarry.h" - -void -sa_init (SA * array) -{ - array->count = 0; - array->array = NULL; -} - -void -sa_add (SA * array, const char *str) -{ - array->array = array->count - ? xrealloc (array->array, sizeof (char *) * (array->count + 1)) - : xmalloc (sizeof (char *)); - array->array[array->count++] = xstrdup (str); -} - -void -sa_cleanup (SA * array) -{ - size_t n = array->count; - while (n--) - xfree (array->array[n]); - xfree (array->array); -} diff --git a/tar.c b/tar.cc similarity index 89% rename from tar.c rename to tar.cc index 5679d8eb..267c58ae 100644 --- a/tar.c +++ b/tar.cc @@ -13,11 +13,19 @@ * */ +/* Built-in tar functionality. See tar.h for usage. */ + +#include "win32.h" #include #include -#include +#include +#include + #include "zlib/zlib.h" #include "tar.h" +#include "mkdir.h" + +#include "port.h" #define FACTOR (0x19db1ded53ea710LL) #define NSPERSEC 10000000LL @@ -60,12 +68,13 @@ 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 gzFile g = 0; static char * xstrdup (char *c) @@ -80,10 +89,15 @@ xstrdup (char *c) 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) { @@ -96,6 +110,12 @@ tar_open (char *pathname) return g ? 0 : 1; } +int +tar_ftell () +{ + return gzctell (g); +} + static void skip_file () { @@ -189,71 +209,6 @@ tar_next_file () } } -static char mkdir_last_warn [_MAX_PATH] = { 0 }; - -static int -mkdir_p (int isadir, char *path) -{ - char saved_char, *slash = 0; - char *c; - DWORD d, gse; - - vp2 (_tar_vfile, "mkdir_p checking %d %s\n", isadir, path); - d = GetFileAttributes (path); - if (d != 0xffffffff && d & FILE_ATTRIBUTE_DIRECTORY) - { - vp2 (_tar_vfile, "mkdir_p it's a directory\n"); - return 0; - } - - if (isadir) - { - vp2 (_tar_vfile, "mkdir_p mkdir %s\n", path); - if (CreateDirectory (path, 0)) - return 0; - gse = GetLastError (); - if (gse != ERROR_PATH_NOT_FOUND) - { - vp2 (_tar_vfile, "mkdir_p returned %d\n", gse); - if (gse == ERROR_ALREADY_EXISTS) - { - if (DeleteFileA (path)) - { - fprintf(stderr, "warning: deleting \"%s\" so I can make a directory there\n", - 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); -} - static void fix_time_stamp (char *path) { diff --git a/tar.exe.gz b/tar.exe.gz deleted file mode 100755 index dd07c45a49d6603504a4b3e98362a756b6555c2d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 54468 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 P@ZbLf+_Z1L0L%dZ=oU=n diff --git a/tar.h b/tar.h index 85d9fb00..e299481f 100644 --- a/tar.h +++ b/tar.h @@ -25,6 +25,9 @@ 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); @@ -36,6 +39,8 @@ int tar_close (); 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; diff --git a/win32.h b/win32.h new file mode 100644 index 00000000..d6bd11ba --- /dev/null +++ b/win32.h @@ -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 + * + */ + +/* 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. */ + +#define _UNION_NAME(x) +#define _STRUCT_NAME(x) +#define NOCOMATTRIBUTE + +#include +#include +#include +#include +#include +#include +#include + +#include diff --git a/xsystem.c b/xsystem.c deleted file mode 100644 index 8172792b..00000000 --- a/xsystem.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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 Ron Parker - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "setup.h" -#include "strarry.h" - -extern char *pathcat (const char *, const char *); - -DWORD -xcreate_process (int wait, HANDLE in, HANDLE out, HANDLE err, const char *cmd) -{ - int retval; - char *command; - STARTUPINFO si; - PROCESS_INFORMATION pi; - extern char *wd; - - if (cmd[1] != ':' && strncmp (cmd, "\\\\", 2) != 0) - command = pathcat (wd, cmd); - else - command = xstrdup (cmd); - - memset (&si, 0, sizeof (si)); - si.cb = sizeof (si); - - si.hStdInput = in ? in : GetStdHandle (STD_INPUT_HANDLE); - si.hStdOutput = out ? out : GetStdHandle (STD_OUTPUT_HANDLE); - si.hStdError = err ? err : GetStdHandle (STD_ERROR_HANDLE); - si.dwFlags = STARTF_USESTDHANDLES; - - retval = CreateProcess (NULL, command, NULL, NULL, TRUE, 0, - NULL, NULL, &si, &pi); - - xfree (command); - if (!retval) - return 0; - - CloseHandle (pi.hThread); - - if (!wait) - retval = (DWORD) pi.hProcess; - else - { - WaitForSingleObject (pi.hProcess, INFINITE); - CloseHandle (pi.hProcess); - } - - return retval; -} - -int -xsystem (const char *cmd) -{ - return !xcreate_process (1, NULL, NULL, NULL, cmd); -} diff --git a/zlib.dsp b/zlib.dsp deleted file mode 100644 index 2c58c798..00000000 --- a/zlib.dsp +++ /dev/null @@ -1,192 +0,0 @@ -# Microsoft Developer Studio Project File - Name="zlib" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Static Library" 0x0104 - -CFG=zlib - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "zlib.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "zlib.mak" CFG="zlib - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "zlib - Win32 Release" (based on "Win32 (x86) Static Library") -!MESSAGE "zlib - Win32 Debug" (based on "Win32 (x86) Static Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "zlib - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c -# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo - -!ELSEIF "$(CFG)" == "zlib - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /i ".." /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo - -!ENDIF - -# Begin Target - -# Name "zlib - Win32 Release" -# Name "zlib - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\zlib\adler32.c -# End Source File -# Begin Source File - -SOURCE=.\zlib\compress.c -# End Source File -# Begin Source File - -SOURCE=.\zlib\crc32.c -# End Source File -# Begin Source File - -SOURCE=.\zlib\deflate.c -# End Source File -# Begin Source File - -SOURCE=.\zlib\gzio.c -# End Source File -# Begin Source File - -SOURCE=.\zlib\infblock.c -# End Source File -# Begin Source File - -SOURCE=.\zlib\infcodes.c -# End Source File -# Begin Source File - -SOURCE=.\zlib\inffast.c -# End Source File -# Begin Source File - -SOURCE=.\zlib\inflate.c -# End Source File -# Begin Source File - -SOURCE=.\zlib\inftrees.c -# End Source File -# Begin Source File - -SOURCE=.\zlib\infutil.c -# End Source File -# Begin Source File - -SOURCE=.\zlib\trees.c -# End Source File -# Begin Source File - -SOURCE=.\zlib\uncompr.c -# End Source File -# Begin Source File - -SOURCE=.\zlib\zutil.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=.\zlib\deflate.h -# End Source File -# Begin Source File - -SOURCE=.\zlib\infblock.h -# End Source File -# Begin Source File - -SOURCE=.\zlib\infcodes.h -# End Source File -# Begin Source File - -SOURCE=.\zlib\inffast.h -# End Source File -# Begin Source File - -SOURCE=.\zlib\inffixed.h -# End Source File -# Begin Source File - -SOURCE=.\zlib\inftrees.h -# End Source File -# Begin Source File - -SOURCE=.\zlib\infutil.h -# End Source File -# Begin Source File - -SOURCE=.\zlib\trees.h -# End Source File -# Begin Source File - -SOURCE=.\zlib\zconf.h -# End Source File -# Begin Source File - -SOURCE=.\zlib\zlib.h -# End Source File -# Begin Source File - -SOURCE=.\zlib\zutil.h -# End Source File -# End Group -# End Target -# End Project diff --git a/zlib/gzio.c b/zlib/gzio.c index 2fd53b75..7fdf984b 100644 --- a/zlib/gzio.c +++ b/zlib/gzio.c @@ -211,6 +211,7 @@ int ZEXPORT gzsetparams (file, level, strategy) int level; int strategy; { +#ifndef NO_DEFLATE gz_stream *s = (gz_stream*)file; if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; @@ -226,6 +227,9 @@ int ZEXPORT gzsetparams (file, level, strategy) } return deflateParams (&(s->stream), level, strategy); +#else + return Z_OK; +#endif } /* =========================================================================== @@ -771,6 +775,18 @@ z_off_t ZEXPORT gztell (file) return gzseek(file, 0L, SEEK_CUR); } +/* =========================================================================== + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. +*/ +z_off_t ZEXPORT gzctell (file) + gzFile file; +{ + gz_stream *s = (gz_stream *)file; + return ftell(s->file); +} + /* =========================================================================== Returns 1 when EOF has previously been detected reading the given input stream, otherwise zero. diff --git a/zlib/zlib.h b/zlib/zlib.h index 47a75cf0..128d9d60 100644 --- a/zlib/zlib.h +++ b/zlib/zlib.h @@ -788,6 +788,11 @@ ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) */ +ZEXTERN z_off_t ZEXPORT gzctell OF((gzFile file)); +/* + current position of compressed file +*/ + ZEXTERN int ZEXPORT gzeof OF((gzFile file)); /* Returns 1 when EOF has previously been detected reading the given -- 2.43.5