]> cygwin.com Git - cygwin-apps/setup.git/commitdiff
* cygcalls.c: new, call cygwin1.dll functions directly
authorDJ Delorie <dj@redhat.com>
Thu, 8 Jun 2000 03:03:16 +0000 (03:03 +0000)
committerDJ Delorie <dj@redhat.com>
Thu, 8 Jun 2000 03:03:16 +0000 (03:03 +0000)
* cygcalls.h: header for same
* Makefile.in: add cygcalls.[ch], remove mount/cygpath/umount
exes, fix cinstall.rc dependencies.
* path.c: remove unneeded code
* setup.c: use cygcalls instead of xcreate_process.
uncompress embedded files with zlib
add "-d" for "download only"
add "-h" for help
postpone mount changes until very end
add download progress indicators
pack multi-column listings more
auto-delete temp files
customize banner message according to options
prompt user for text/binary mounts
add warnings about empty setup directory, root installs, etc

ChangeLog
Makefile.in
cygcalls.c [new file with mode: 0644]
cygcalls.h [new file with mode: 0644]
path.c
setup.c

index f338fd298afcd1c8820f01e9b01acad1a89f33a3..d92f196da947198d62e7df001fd5d3ce37079add 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2000-06-07  DJ Delorie  <dj@cygnus.com>
+
+       * cygcalls.c: new, call cygwin1.dll functions directly
+       * cygcalls.h: header for same
+       * Makefile.in: add cygcalls.[ch], remove mount/cygpath/umount
+       exes, fix cinstall.rc dependencies.
+       * path.c: remove unneeded code
+       * setup.c: use cygcalls instead of xcreate_process.
+       uncompress embedded files with zlib
+       add "-d" for "download only"
+       add "-h" for help
+       postpone mount changes until very end
+       add download progress indicators
+       pack multi-column listings more
+       auto-delete temp files
+       customize banner message according to options
+       prompt user for text/binary mounts
+       add warnings about empty setup directory, root installs, etc
+
 2000-05-24  DJ Delorie  <dj@cygnus.com>
 
        * tar.c: New file; built-in tar using zlib.
index 7bd3504fed09dc55032afcad9cc84c15b7bf11c0..18db4e6d58fd55f24f501ed39b0eaf96528a9c94 100644 (file)
@@ -67,10 +67,10 @@ ALL_LDFLAGS:=${filter-out -I%, \
 
 PROGS:=setup$(EXEEXT)
 
-OBJS:=error.o memory.o setup.o strarry.o cinstall.o path.o pkg.o tar.o xsystem.o
+OBJS:=cygcalls.o error.o memory.o setup.o strarry.o cinstall.o path.o pkg.o tar.o xsystem.o
 
-BUNDLED_FILES:=cygwin1.dll.gz \
-              mount.exe.gz cygpath.exe.gz umount.exe.gz
+BUNDLED_FILES:=cygwin1.dll.gz
+#             mount.exe.gz cygpath.exe.gz umount.exe.gz
 .SUFFIXES:
 .NOEXPORT:
 
@@ -83,8 +83,8 @@ setup$(EXEEXT): $(OBJS) $(ALL_DEP_LDLIBS)
 ifdef VERBOSE
        $(CC) -o $@ ${filter-out $(ALL_DEP_LIBS),$^}
 else
-       @echo $(CC) -o $@ ${filter-out $(ALL_DEP_LIBS),$^} ${filter-out -B%, $(ALL_LDFLAGS) $(ALL_LDLIBS)};\
-       $(CC) -o $@ ${filter-out $(ALL_DEP_LIBS),$^} $(ALL_LDFLAGS) $(ALL_LDLIBS)
+       @echo $(CC) ... -o $@ $(OBJS)
+       @$(CC) -o $@ ${filter-out $(ALL_DEP_LIBS),$^} $(ALL_LDFLAGS) $(ALL_LDLIBS)
 endif
        @chmod a-x $@
 
@@ -131,8 +131,8 @@ $(utils_build)/%.exe: $(utils_build)/Makefile
 $(cygwin_build)/%.dll: $(cygwin_build)/Makefile
        @$(MAKE) -C $(@D) $(@F)
 
-cinstall.rc: $(BUNDLED_FILES)
-       for f in $^; do \
+cinstall.rc: $(BUNDLED_FILES) $(srcdir)/Makefile.in
+       for f in $(BUNDLED_FILES); do \
            echo `basename $$f .gz` FILE DISCARDABLE '"'$$f'"'; \
        done > $@
 
@@ -143,6 +143,6 @@ cinstall.rc: $(BUNDLED_FILES)
 ifdef VERBOSE
        $(CC) $(MINGW_CFLAGS) -c -o $@ $?
 else
-       @echo $(CC) -c -o $@ $? ${filter-out -B%, $(MINGW_CFLAGS)};\
-       $(CC) $(MINGW_CFLAGS) -c -o $@ $?
+       @echo $(CC) -c $(CFLAGS) ... $(?F)
+       @$(CC) $(MINGW_CFLAGS) -c -o $@ $?
 endif
diff --git a/cygcalls.c b/cygcalls.c
new file mode 100644 (file)
index 0000000..03dba45
--- /dev/null
@@ -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 <dj@cygnus.com>
+ *
+ */
+
+#include <windows.h>
+#include <stdio.h>
+
+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/cygcalls.h b/cygcalls.h
new file mode 100644 (file)
index 0000000..329e536
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2000, Red Hat, Inc.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     A copy of the GNU General Public License can be found at
+ *     http://www.gnu.org/
+ *
+ * Written by DJ Delorie <dj@cygnus.com>
+ *
+ */
+
+#include "../cygwin/include/sys/mount.h"
+#include "../cygwin/include/mntent.h"
+
+/* returns zero on success, nonzero on failure */
+int cygcall_load_dll (char *name); 
+
+int cygcall_unload_dll (); 
diff --git a/path.c b/path.c
index 0162306047b3216321681924ff8eaba9dff1a6db..183df0157a0725b7657296d7d9bf7ffaefd8083a 100644 (file)
--- a/path.c
+++ b/path.c
@@ -33,6 +33,8 @@
 #include "strarry.h"
 #include "zlib/zlib.h"
 
+#if 0
+
 static FILE *cygin = NULL, *cygout = NULL;
 static HANDLE hcygpath = NULL;
 
@@ -129,6 +131,8 @@ utodpath (const char *path)
   return retval;
 }
 
+#endif /* 0 */
+
 char *
 pathcat (const char *arg1, const char *arg2)
 {
diff --git a/setup.c b/setup.c
index 38ca517314316a7fcf2cb44360e18dd81a90086d..4f3aa08763969f6ce8870d9fa27ac6b5643b45dd 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -35,6 +35,7 @@
 #include "setup.h"
 #include "strarry.h"
 #include "zlib/zlib.h"
+#include "cygcalls.h"
 
 #define MIRRORFILE "http://sourceware.cygnus.com/cygwin/mirrors.html"
 
@@ -67,25 +68,32 @@ 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 (100);
+      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 ();
@@ -248,15 +256,121 @@ output_file (HMODULE h __attribute__ ((unused)),
   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
-xumount (const char *mountexedir, const char *unixpath)
+save_resource_as_file (char *resource_name, char *file_name)
 {
-  char *umount = pathcat (mountexedir, "umount");
-  char buffer[1024];
+  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);
+       }
+    }
 
-  sprintf (buffer, "%s %s", umount, unixpath);
-  (void) xcreate_process (1, NULL, devnull, devnull, buffer);
-  xfree (umount);
+  inflateEnd (&z);
+  fclose (out);
+}
+
+static void
+xumount (const char *mountexedir, const char *unixpath)
+{
+  umount (unixpath);
 }
 
 extern FILE * _tar_vfile;
@@ -461,6 +575,7 @@ optionprompt (const char *text, SA * options)
   char buf[5];
   size_t base;
   int maxwidth=0, skip, percol;
+  int screen_lines = SCREEN_LINES;
 
   for (n=0; n<options->count; n++)
     {
@@ -468,12 +583,14 @@ optionprompt (const char *text, SA * options)
       if (maxwidth < sl)
        maxwidth = sl;
     }
+
   ncols = SCREEN_COLS / (maxwidth + 5);
   skip = (options->count + ncols - 1) / ncols;
-  printf("count = %d   ncols = %d   skip = %d\n",
-        options->count, ncols, skip);
   percol = SCREEN_COLS / ncols;
 
+  if (options->count < ncols * screen_lines)
+    screen_lines = (options->count+ncols-1)/ncols;
+
   base = 0;
 
   puts (text);
@@ -482,25 +599,25 @@ optionprompt (const char *text, SA * options)
     {
       char *repeat, *enter;
 
-      for (n = 0; n < SCREEN_LINES; n++)
+      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;
+             unsigned i = n + base + c * screen_lines;
              if (i < options->count)
-               printf("%2d. %-*s", i + 1, percol - 5, options->array[i]);
+               printf ("%2d. %-*s", i + 1, percol - 5, options->array[i]);
            }
-         printf("\n");
+         printf ("\n");
        }
 
       repeat = enter = "";
-      if (skip > SCREEN_LINES)
+      if (skip > screen_lines)
        {
          if (base)
            repeat = " or `R' to repeat the list";
-         if (base + SCREEN_LINES * ncols < options->count)
+         if (base + screen_lines * ncols < options->count)
            enter = " or [Enter] for more options";
        }
 
@@ -517,8 +634,8 @@ optionprompt (const char *text, SA * options)
 
       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 (base + screen_lines * ncols < options->count)
+           base += screen_lines * ncols;
        }
       if (buf[0] == 'r' || buf[0] == 'R')
        base = 0;
@@ -594,7 +711,7 @@ geturl (const char *url, const char *file, int verbose)
       if (verbose)
        {
          if (tries > 1)
-           printf ("\r%s        \b\b\b\b\b\b\b\b", connect_buffer);
+           printf ("\r%s        \r", connect_buffer);
          printf ("Done.\n"); fflush (stdout);
        }
       while (!authenticated)
@@ -689,14 +806,28 @@ geturl (const char *url, const char *file, int verbose)
            winerror ();
          else
            {
-             char *buffer = xmalloc (size);
+             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);
 
-             FILE *out = fopen (file, "wb");
+             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;
@@ -714,7 +845,18 @@ geturl (const char *url, const char *file, int verbose)
                                  _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);
@@ -867,16 +1009,19 @@ processdirlisting (SA *installme, const char *urlbase, const char *file)
 
          retval++;
 
-         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))
+         if (!download_only)
            {
-             warning ("Skipped download of %s\n", filename);
-             continue;
+             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))
@@ -978,7 +1123,9 @@ processdirlisting (SA *installme, const char *urlbase, const char *file)
 static char *
 tmpfilename ()
 {
-  return _tempnam (NULL, "su");
+  char *rv = _tempnam (NULL, "su");
+  sa_add (&deleteme, rv);
+  return rv;
 }
 
 static int
@@ -988,10 +1135,8 @@ downloaddir (SA *installme, const char *url)
   char *file = tmpfilename ();
 
   if (geturl (url, file, 1))
-  {
     retval = processdirlisting (installme, url, file);
-    _unlink (file);
-  }
+  _unlink (file);
   xfree (file);
 
   return retval;
@@ -1011,10 +1156,8 @@ downloadfrom (SA *installme, const char *url)
   char *file = tmpfilename ();
 
   if (geturl (url, file, 1))
-    {
-      retval = processdirlisting (installme, url, file);
-      _unlink (file);
-    }
+    retval = processdirlisting (installme, url, file);
+  _unlink (file);
 
   xfree (file);
 
@@ -1292,35 +1435,32 @@ mkdirp (const char *dir)
 
 /* This routine assumes that the cwd is the root directory. */
 static int
-mkmount (const char *mountexedir, const char *dospath,
-        const char *unixpath, int force)
+mkmount (const char *dospath, const char *unixpath)
 {
-  char *mount, *fulldospath;
-  char buffer[1024];
+  char *mountd, *fulldospath;
 
-  if (root == NULL)
-    fulldospath = xstrdup (dospath);
-  else
+  assert (root != NULL);
+
+  if (dospath[0])
     {
-      xumount (mountexedir, unixpath);
       /* Make sure the mount point exists. */
-      mount = utodpath (unixpath);
-      mkdirp (mount);
-      xfree (mount);
+      mountd = pathcat (root, unixpath);
+      mkdirp (mountd);
+      xfree (mountd);
       fulldospath = pathcat (root, dospath);
     }
+  else
+    {
+      fulldospath = xstrdup (root);
+    }
 
   /* Make sure the target path exists. */
   mkdirp (fulldospath);
 
-  /* Mount the directory. */
-  mount = pathcat (mountexedir, "mount");
-  sprintf (buffer, "%s %s -b \"%s\" %s", mount, force ? "-f" : "",
-          fulldospath, unixpath);
-  xfree (mount);
-  xfree (fulldospath);
+  umount (unixpath);
+  mount (fulldospath, unixpath, mount_text ? 0 : MOUNT_BINARY);
 
-  return xcreate_process (1, NULL, NULL, NULL, buffer) != 0;
+  xfree (fulldospath);
 }
 
 static pkg *
@@ -1385,38 +1525,72 @@ current_directory_not_empty ()
   if (h != INVALID_HANDLE_VALUE)
     do
       {
-       if (strcmp (find_data.cFileName, ".")
-           && strcmp (find_data.cFileName, ".."))
+       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 __attribute__ ((unused)), char **argv)
+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);
-
-  while (*++argv)
-    if (stricmp (*argv, "-f") == 0)
-      updating = 0;
-    else if (stricmp (*argv, "-u") == 0)
-      updating = 1;
-    else
-      break;
+  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);
-  if (*argv)
-    do
-      sa_add (&installme, *argv);
-    while (*++argv);
+  while (argc > 1)
+    {
+      sa_add (&installme, argv[1]);
+      argc--;
+      argv++;
+    }
 
   devnull = (HANDLE) _get_osfhandle (fd);
 
@@ -1433,75 +1607,82 @@ main (int argc __attribute__ ((unused)), char **argv)
       p[1] = '\0';
     }
 
-  printf ( "\n\n\n\n"
-"This is the Cygwin setup utility%s,\n"
-"built on " __DATE__ " " __TIME__ ".\n\n"
+  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
-those as the basis for your installation.\n\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", revn);
+"temporary directory.\n\n");
 
   start = clock ();
   sa_init (&deleteme);
 
-  if (!EnumResourceNames (NULL, "FILE", output_file, 0))
+  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))
     {
-      winerror ();
+#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;
+       }
     }
-  else
-    {
-      char *defroot, *update;
-      char *tmp;
-      int done;
-      HKEY cu = NULL, lm = NULL;
+  if (!defroot)
+    defroot = xstrdup (DEF_ROOT);
 
-      wd = _getcwd (NULL, 0);
-      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");
+  setpath (wd);
+  tmp = xmalloc (sizeof ("TMP=") + strlen (wd));
+  sprintf (tmp, "TMP=%s", wd);
+  _putenv (tmp);
 
-      if (logpath)
-       logfp = fopen (logpath, "wt");
+  logpath = pathcat (wd, "setup.log");
+  tarpgm = pathcat (wd, "tar.exe");
 
-      if (logfp == NULL)
-       {
-         fprintf (stderr, "Unable to open log file '%s' for writing - %s\n",
-                  logpath, _strerror (""));
-         exit (1);
-       }
+  if (logpath)
+    logfp = fopen (logpath, "wt");
 
-      /* Begin prompting user for setup requirements. */
-      printf ("Press <enter> to accept the default value.\n");
+  if (logfp == NULL)
+    {
+      fprintf (stderr, "Unable to open log file '%s' for writing - %s\n",
+              logpath, _strerror (""));
+      exit (1);
+    }
 
-      /* If some Cygnus software has been installed, assume there is a root
-        mount in the registry. Otherwise use C:\cygwin for the default root
-        directory. */
-      if (RegOpenKey (HKEY_CURRENT_USER, CYGNUS_KEY, &cu) == ERROR_SUCCESS
-         || RegOpenKey (HKEY_LOCAL_MACHINE, CYGNUS_KEY,
-                        &lm) == ERROR_SUCCESS)
-       {
-         defroot = utodpath ("/");
-         if (cu)
-           RegCloseKey (cu);
-         if (lm)
-           RegCloseKey (lm);
-       }
-      else
-       defroot = xstrdup (DEF_ROOT);
+  /* Begin prompting user for setup requirements. */
+  printf ("Press <enter> 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);
+  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;)
@@ -1545,51 +1726,98 @@ those as the basis for your installation.\n\n"
              y = yesno[0];
              free (yesno);
              if (y != 'y' && y != 'Y')
-                 continue;
+               continue;
            }
          done = 1;
        }
       xfree (defroot);
 
-      Sleep (0);
+      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 (toupper (*update) == 'I')
+    {
+      char *dir;
 
-         if (current_directory_not_empty ())
-           {
-             fprintf (stderr, "\nThe current directory is not empty.  Please run setup in an\n");
-             fprintf (stderr, "empty temporary directory when installing from the Internet.\n\n");
-             exit (1);
-           }
+      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 ();
+      dir = getdownloadsource ();
 
-         if (!dir)
-           {
-             fprintf (stderr, "Couldn't connect to download site.\n");
-             exit (1);
-           }
+      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);
+      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;
        }
-      xfree (update);
+      InternetCloseHandle (session);
+      xfree (dir);
+    }
+  xfree (update);
+
+  if (! download_only)
+    {
 
       /* Create the root directory. */
       mkdirp (root);           /* Ignore any return value since it may
@@ -1647,32 +1875,30 @@ those as the basis for your installation.\n\n"
                                   successful code */
 
              warning ("Creating mount points...");
-             xumount (wd, "/usr");
-             xumount (wd, "/var");
-             xumount (wd, "/lib");
-             xumount (wd, "/bin");
-             xumount (wd, "/etc");
+             umount ("/usr");
+             umount ("/var");
+             umount ("/lib");
+             umount ("/bin");
+             umount ("/etc");
              
              /* Make /bin point to /usr/bin and /lib point to /usr/lib. */
-             mkmount (wd, "", "/", 1);
-             mkmount (wd, "bin", "/usr/bin", 1);
-             mkmount (wd, "lib", "/usr/lib", 1);
+             mkmount ("", "/");
+             mkmount ("bin", "/usr/bin");
+             mkmount ("lib", "/usr/lib");
 
            }
        }
+    }
 
-      xfree (root);
-
-      chdir (wd);
-      _chdrive (toupper (*wd) - 'A' + 1);
-      xfree (wd);
+  xfree (root);
 
-    }
+  chdir (wd);
+  _chdrive (toupper (*wd) - 'A' + 1);
 
 out:
   puts ("");
   warning ("Installation took %.0f seconds.\n",
-         (double) (clock () - start) / CLK_TCK);
+          (double) (clock () - start) / CLK_TCK);
 
   if (logpath)
     {
This page took 0.095823 seconds and 5 git commands to generate.