OSDN Git Service

* cygcheck.cc (pathlike): New class.
authorcgf <cgf>
Mon, 4 Jun 2007 01:57:16 +0000 (01:57 +0000)
committercgf <cgf>
Mon, 4 Jun 2007 01:57:16 +0000 (01:57 +0000)
(paths): Redefine as type pathlike.
(display_error): Declare a few different ways to allow more flexible usage
throughout.
(display_error_fmt): New function for those cases where C++ just isn't enough.
(add_path): Rewrite to allocate pathlike paths.  Always tack on a trailing
slash since that's what everyone who uses it wants.  NULL terminate the path
list.  Register "it's a system path" field.
(init_path): Call add_path with info regarding whether path is a system path or
not.
(pathlike::check_existence): Move into pathlike class.  Accept file and
extension arguments to build up path on the fly.  Modify other arguments.
(find_on_path): Constify return value and appropriate arguments.  Eliminate
short-circuit for fully-qualified paths.  Simplify loop which iterates over
path.
(already_did): Constify argument.
(track_down): Ditto.  Regularize some error messages.
(find_app_on_path): Ditto.
(cygcheck): Constify argument.  Use 20th century string handling functions.
(dump_sysinfo): Remove odd inclusion of '\\bin' "Just in case".  Accommodate
change of paths to pathlike.
* path.cc (isslash): Rename from SLASH_P and use throughout.
(rel_vconcat): Front-end to vconcat which prepends cwd to path before passing
along for conversion to native windows.
(cygpath): Remove "./" test.  Call rel_vconcat if filename appears to be
relative.

winsup/utils/ChangeLog
winsup/utils/cygcheck.cc
winsup/utils/path.cc

index fc839a4..7a0c80d 100644 (file)
@@ -1,3 +1,35 @@
+2007-06-03  Christopher Faylor  <me+cygwin@cgf.cx>
+
+       * cygcheck.cc (pathlike): New class.
+       (paths): Redefine as type pathlike.
+       (display_error): Declare a few different ways to allow more flexible
+       usage throughout.
+       (display_error_fmt): New function for those cases where C++ just isn't
+       enough.
+       (add_path): Rewrite to allocate pathlike paths.  Always tack on a
+       trailing slash since that's what everyone who uses it wants.  NULL
+       terminate the path list.  Register "it's a system path" field.
+       (init_path): Call add_path with info regarding whether path is a system
+       path or not.
+       (pathlike::check_existence): Move into pathlike class.  Accept file and
+       extension arguments to build up path on the fly.  Modify other
+       arguments.
+       (find_on_path): Constify return value and appropriate arguments.
+       Eliminate short-circuit for fully-qualified paths.  Simplify loop which
+       iterates over path.
+       (already_did): Constify argument.
+       (track_down): Ditto.  Regularize some error messages.
+       (find_app_on_path): Ditto.
+       (cygcheck): Constify argument.  Use 20th century string handling
+       functions.
+       (dump_sysinfo): Remove odd inclusion of '\\bin' "Just in case".
+       Accommodate change of paths to pathlike.
+       * path.cc (isslash): Rename from SLASH_P and use throughout.
+       (rel_vconcat): Front-end to vconcat which prepends cwd to path before
+       passing along for conversion to native windows.
+       (cygpath): Remove "./" test.  Call rel_vconcat if filename appears to
+       be relative.
+
 2007-05-29  Pedro Alves  <pedro_alves@portugalmail.pt>
 
        * dumper.cc (dumper::prepare_core_dump): Record a phdr for each section.
index 94498aa..b75f38f 100644 (file)
@@ -38,6 +38,8 @@ int find_package = 0;
 int list_package = 0;
 int grep_packages = 0;
 
+static char emptystr[] = "";
+
 /* This is global because it's used in both internet_display_error as well
    as package_grep.  */
 BOOL (WINAPI *pInternetCloseHandle) (HINTERNET);
@@ -114,7 +116,16 @@ static common_apps[] = {
 };
 
 static int num_paths, max_paths;
-static char **paths;
+struct pathlike
+{
+  char *dir;
+  bool issys;
+  void pathlike::check_existence (const char *fn, int showall, int verbose,
+                                 char* first, const char *ext1 = "",
+                                 const char *ext2 = "");
+};
+
+pathlike *paths;
 int first_nonsys_path;
 
 void
@@ -130,17 +141,43 @@ eprintf (const char *format, ...)
  * display_error() is used to report failure modes
  */
 static int
-display_error (const char *name, bool show_error = true, bool print_failed = true)
+display_error (const char *name, bool show_error, bool print_failed)
 {
+  fprintf (stderr, "cygcheck: %s", name);
   if (show_error)
-    fprintf (stderr, "cygcheck: %s%s: %lu\n", name,
+    fprintf (stderr, "%s: %lu\n",
        print_failed ? " failed" : "", GetLastError ());
   else
-    fprintf (stderr, "cygcheck: %s%s\n", name,
+    fprintf (stderr, "%s\n",
        print_failed ? " failed" : "");
   return 1;
 }
 
+static int
+display_error (const char *name)
+{
+  return display_error (name, true, true);
+}
+
+static int
+display_error (const char *fmt, const char *x)
+{
+  char buf[4000];
+  sprintf (buf, fmt, x);
+  return display_error (buf, false, false);
+}
+
+static int
+display_error_fmt (const char *fmt, ...)
+{
+  char buf[4000];
+  va_list va;
+
+  va_start (va, fmt);
+  vsprintf (buf, fmt, va);
+  return display_error (buf, false, false);
+}
+
 /* Display a WinInet error message, and close a variable number of handles.
    (Passed a list of handles terminated by NULL.)  */
 static int
@@ -156,12 +193,12 @@ display_internet_error (const char *message, ...)
   if (err)
     {
       if (FormatMessage (FORMAT_MESSAGE_FROM_HMODULE,
-          GetModuleHandle ("wininet.dll"), err, 0, err_buf,
-          sizeof (err_buf), NULL) == 0)
-        strcpy (err_buf, "(Unknown error)");
+         GetModuleHandle ("wininet.dll"), err, 0, err_buf,
+         sizeof (err_buf), NULL) == 0)
+       strcpy (err_buf, "(Unknown error)");
 
       fprintf (stderr, "cygcheck: %s: %s (win32 error %d)\n", message,
-               err_buf, err);
+              err_buf, err);
     }
   else
     fprintf (stderr, "cygcheck: %s\n", message);
@@ -175,33 +212,37 @@ display_internet_error (const char *message, ...)
 }
 
 static void
-add_path (char *s, int maxlen)
+add_path (char *s, int maxlen, bool issys)
 {
   if (num_paths >= max_paths)
     {
       max_paths += 10;
-      if (paths)
-       paths = (char **) realloc (paths, max_paths * sizeof (char *));
-      else
-       paths = (char **) malloc (max_paths * sizeof (char *));
+      /* Extend path array */
+      paths = (pathlike *) realloc (paths, (1 + max_paths) * sizeof (paths[0]));
     }
-  paths[num_paths] = (char *) malloc (maxlen + 1);
-  if (paths[num_paths] == NULL)
+
+  pathlike *pth = paths + num_paths;
+
+  /* Allocate space for directory in path list */
+  char *dir = (char *) calloc (maxlen + 2, sizeof (char));
+  if (dir == NULL)
     {
-      display_error ("add_path: malloc()");
+      display_error ("add_path: calloc() failed");
       return;
     }
-  memcpy (paths[num_paths], s, maxlen);
-  paths[num_paths][maxlen] = 0;
-  char *e = paths[num_paths] + strlen (paths[num_paths]);
-  if (e[-1] == '\\' && e[-2] != ':')
-    *--e = 0;
-  for (int i = 1; i < num_paths; i++)
-    if (strcasecmp (paths[num_paths], paths[i]) == 0)
-      {
-       free (paths[num_paths]);
-       return;
-      }
+
+  /* Copy input directory to path list */
+  memcpy (dir, s, maxlen);
+
+  /* Add a trailing slash by default */
+  char *e = strchr (dir, '\0');
+  if (e != dir && e[-1] != '\\')
+    strcpy (e, "\\");
+
+  /* Fill out this element */
+  pth->dir = dir;
+  pth->issys = issys;
+  pth[1].dir = NULL;
   num_paths++;
 }
 
@@ -209,39 +250,39 @@ static void
 init_paths ()
 {
   char tmp[4000], *sl;
-  add_path ((char *) ".", 1);  /* to be replaced later */
+  add_path ((char *) ".", 1, true);    /* to be replaced later */
 
   if (GetCurrentDirectory (4000, tmp))
-    add_path (tmp, strlen (tmp));
+    add_path (tmp, strlen (tmp), true);
   else
     display_error ("init_paths: GetCurrentDirectory()");
 
   if (GetSystemDirectory (tmp, 4000))
-    add_path (tmp, strlen (tmp));
+    add_path (tmp, strlen (tmp), true);
   else
     display_error ("init_paths: GetSystemDirectory()");
   sl = strrchr (tmp, '\\');
   if (sl)
     {
       strcpy (sl, "\\SYSTEM");
-      add_path (tmp, strlen (tmp));
+      add_path (tmp, strlen (tmp), true);
     }
   GetWindowsDirectory (tmp, 4000);
-  add_path (tmp, strlen (tmp));
-  first_nonsys_path = num_paths;
+  add_path (tmp, strlen (tmp), true);
 
   char *wpath = getenv ("PATH");
   if (!wpath)
-    fprintf (stderr, "WARNING: PATH is not set at all!\n");
+    display_error ("WARNING: PATH is not set\n", "");
   else
     {
       char *b, *e;
       b = wpath;
       while (1)
        {
-         for (e = b; *e && *e != ';'; e++);
-         if (strncmp(b, ".", 1) && strncmp(b, ".\\", 2))
-           add_path (b, e - b);
+         for (e = b; *e && *e != ';'; e++)
+           continue;   /* loop terminates at first ';' or EOS */
+         if (strncmp(b, ".\\", 2) != 0)
+           add_path (b, e - b, false);
          if (!*e)
            break;
          b = e + 1;
@@ -251,9 +292,16 @@ init_paths ()
 
 #define LINK_EXTENSION ".lnk"
 
-static bool
-check_existence (char *file, int showall, int foundone, char *first)
+void
+pathlike::check_existence (const char *fn, int showall, int verbose,
+                          char* first, const char *ext1, const char *ext2)
 {
+  char file[4000];
+  strcpy (file, dir);
+  strcat (file, fn);
+  strcat (file, ext1);
+  strcat (file, ext2);
+
   if (GetFileAttributes (file) != (DWORD) - 1)
     {
       char *lastdot = strrchr (file, '.');
@@ -263,7 +311,7 @@ check_existence (char *file, int showall, int foundone, char *first)
        *lastdot = '\0';
       if (showall)
        printf ("Found: %s\n", file);
-      if (foundone)
+      if (verbose && *first != '\0' && strcasecmp (first, file) != 0)
        {
          char *flastdot = strrchr (first, '.');
          bool f_is_link = flastdot && !strcmp (flastdot, LINK_EXTENSION);
@@ -276,84 +324,81 @@ check_existence (char *file, int showall, int foundone, char *first)
        }
       if (is_link)
        *lastdot = '.';
-      return true;
+      if (!*first)
+       strcpy (first, file);
     }
-  return false;
 }
 
-static char *
-find_on_path (char *file, char *default_extension,
-             int showall = 0, int search_sysdirs = 0, int checklinks = 0)
+static const char *
+find_on_path (const char *in_file, const char *ext, bool showall = false,
+             bool search_sys = false, bool checklinks = false)
 {
   static char rv[4000];
-  char tmp[4000], *ptr = rv;
 
-  if (!file)
+  /* Sort of a kludge but we've already tested this once, so don't try it again */
+  if (in_file == rv)
+    return in_file;
+
+  static pathlike abspath[2] =
+  {
+    {emptystr, 0},
+    {NULL, 0}
+  };
+
+  *rv = '\0';
+  if (!in_file)
     {
-      display_error ("find_on_path: NULL pointer for file", false, false);
+      display_error ("internal error find_on_path: NULL pointer for file", false, false);
       return 0;
     }
 
-  if (default_extension == NULL)
+  if (!ext)
     {
-      display_error ("find_on_path: NULL pointer for default_extension", false, false);
+      display_error ("internal error find_on_path: NULL pointer for default_extension", false, false);
       return 0;
     }
 
-  if (strchr (file, ':') || strchr (file, '\\') || strchr (file, '/'))
+  const char *file;
+  pathlike *search_paths;
+  if (!strpbrk (in_file, ":/\\"))
     {
-      // FIXME: this will find "foo" before "foo.exe" -- contrary to Windows
-      char *fn = cygpath (file, NULL);
-      if (access (fn, F_OK) == 0)
-       return fn;
-      strcpy (rv, fn);
-      strcat (rv, default_extension);
-      if (access (rv, F_OK) == 0)
-       return rv;
-      if (!checklinks)
-       return fn;
-      strcat (rv, LINK_EXTENSION);
-      if (access (rv, F_OK) == 0)
-       return rv;
-      strcpy (rv, fn);
-      strcat (rv, LINK_EXTENSION);
-      return access (rv, F_OK) == 0 ? strdup (rv) : fn;
+      file = in_file;
+      search_paths = paths;
+    }
+  else
+    {
+      file = cygpath (in_file, NULL);
+      search_paths = abspath;
+      showall = false;
     }
 
-  if (strchr (file, '.'))
-    default_extension = (char *) "";
-
-  for (int i = search_sysdirs ? 0 : first_nonsys_path; i < num_paths; i++)
+  if (!file)
     {
-      if (i == 0 || !search_sysdirs || strcasecmp (paths[i], paths[0]))
-       {
-         sprintf (ptr, "%s\\%s%s", paths[i], file, default_extension);
-         if (check_existence (ptr, showall, ptr == tmp && verbose, rv))
-           ptr = tmp;
+      display_error ("internal error find_on_path: cygpath conversion failed for %s\n", in_file);
+      return 0;
+    }
 
-         if (!checklinks)
-           continue;
+  char *hasext = strrchr (file, '.');
+  if (hasext && !strpbrk (hasext, "/\\"))
+    ext = "";
 
-         sprintf (ptr, "%s\\%s%s%s", paths[i], file, default_extension, LINK_EXTENSION);
-         if (check_existence (ptr, showall, ptr == tmp && verbose, rv))
-           ptr = tmp;
+  for (pathlike *pth = search_paths; pth->dir; pth++)
+    if (!pth->issys || search_sys)
+      {
+       pth->check_existence (file, showall, verbose, rv, ext);
 
-         if (!*default_extension)
-           continue;
+       if (checklinks)
+         pth->check_existence (file, showall, verbose, rv, ext, LINK_EXTENSION);
 
-         sprintf (ptr, "%s\\%s", paths[i], file);
-         if (check_existence (ptr, showall, ptr == tmp && verbose, rv))
-           ptr = tmp;
-         sprintf (ptr, "%s\\%s%s", paths[i], file, LINK_EXTENSION);
-         if (check_existence (ptr, showall, ptr == tmp && verbose, rv))
-           ptr = tmp;
-       }
-    }
+       if (!*ext)
+         continue;
 
-  if (ptr == tmp)
-    return rv;
+       pth->check_existence (file, showall, verbose, rv);
+       if (checklinks)
+         pth->check_existence (file, showall, verbose, rv, LINK_EXTENSION);
+      }
 
-  return 0;
+  return *rv ? rv : NULL;
 }
 
 #define DID_NEW                1
@@ -369,7 +414,7 @@ struct Did
 static Did *did = 0;
 
 static Did *
-already_did (char *file)
+already_did (const char *file)
 {
   Did *d;
   for (d = did; d; d = d->next)
@@ -440,8 +485,7 @@ struct ImpDirectory
   unsigned iat_rva;
 };
 
-
-static bool track_down (char *file, char *suffix, int lvl);
+static bool track_down (const char *file, const char *suffix, int lvl);
 
 #define CYGPREFIX (sizeof ("%%% Cygwin ") - 1)
 static void
@@ -647,7 +691,7 @@ dll_info (const char *path, HANDLE fh, int lvl, int recurse)
 
 // Return true on success, false if error printed
 static bool
-track_down (char *file, char *suffix, int lvl)
+track_down (const char *file, const char *suffix, int lvl)
 {
   if (file == NULL)
     {
@@ -661,10 +705,10 @@ track_down (char *file, char *suffix, int lvl)
       return false;
     }
 
-  char *path = find_on_path (file, suffix, 0, 1);
+  const char *path = find_on_path (file, suffix, false, true);
   if (!path)
     {
-      printf ("Error: could not find %s\n", file);
+      display_error ("track_down: could not find %s\n", file);
       return false;
     }
 
@@ -700,7 +744,7 @@ track_down (char *file, char *suffix, int lvl)
 
   if (!path)
     {
-      printf ("%s not found\n", file);
+      display_error ("file not found - '%s'\n", file);
       return false;
     }
 
@@ -711,7 +755,7 @@ track_down (char *file, char *suffix, int lvl)
                NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
   if (fh == INVALID_HANDLE_VALUE)
     {
-      printf (" - Cannot open\n");
+      display_error ("cannot open - '%s'\n", path);
       return false;
     }
 
@@ -720,15 +764,15 @@ track_down (char *file, char *suffix, int lvl)
   if (is_exe (fh))
     dll_info (path, fh, lvl, 1);
   else if (is_symlink (fh))
-    printf (" - Found a symlink instead of a DLL\n");
+    display_error ("%s is a symlink instead of a DLL\n", path);
   else
     {
       int magic = get_word (fh, 0x0);
       if (magic == -1)
-        display_error ("get_word");
+       display_error ("get_word");
       magic &= 0x00FFFFFF;
-      printf (" - Not a DLL: magic number %x (%d) '%s'\n",
-              magic, magic, (char *)&magic);
+      display_error_fmt ("%s is not a DLL: magic number %x (%d) '%s'\n",
+                        path, magic, magic, (char *)&magic);
     }
 
   d->state = DID_INACTIVE;
@@ -760,19 +804,16 @@ ls (char *f)
 }
 
 // Find a real application on the path (possibly following symlinks)
-static char *
-find_app_on_path (char *app, int showall = 0)
+static const char *
+find_app_on_path (const char *app, bool showall = false)
 {
-  char *papp = find_on_path (app, (char *) ".exe", showall, 0, 1);
+  const char *papp = find_on_path (app, ".exe", showall, false, true);
 
   HANDLE fh =
     CreateFile (papp, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
                NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
   if (fh == INVALID_HANDLE_VALUE)
-    {
-      printf (" - Cannot open\n");
-      return NULL;
-    }
+    return NULL;
 
   if (is_symlink (fh))
     {
@@ -806,28 +847,33 @@ find_app_on_path (char *app, int showall = 0)
 
 // Return true on success, false if error printed
 static bool
-cygcheck (char *app)
+cygcheck (const char *app)
 {
-  char *papp = find_app_on_path (app, 1);
+  const char *papp = find_app_on_path (app, 1);
   if (!papp)
     {
-      printf ("Error: could not find %s\n", app);
+      display_error ("could not find '%s'\n", app);
       return false;
     }
-  char *s = strdup (papp);
-  char *sl = 0, *t;
-  for (t = s; *t; t++)
-    if (*t == '/' || *t == '\\' || *t == ':')
-      sl = t;
-  if (sl == 0)
-    paths[0] = (char *) ".";
+
+  char *s;
+  char *sep = strpbrk (papp, ":/\\");
+  if (!sep)
+    {
+      static char dot[] = ".";
+      s = dot;
+    }
   else
     {
-      *sl = 0;
-      paths[0] = s;
+      int n = sep - papp;
+      s = (char *) malloc (n + 2);
+      memcpy ((char *) s, papp, n);
+      strcpy (s + n, "\\");
     }
-  did = 0;
-  return track_down (papp, (char *) ".exe", 0);
+
+  paths[0].dir = s;
+  did = NULL;
+  return track_down (papp, ".exe", 0);
 }
 
 
@@ -1192,15 +1238,15 @@ dump_sysinfo ()
          else if (osversion.dwMinorVersion == 1)
            {
              if (GetSystemMetrics (SM_MEDIACENTER))
-               osname = "XP Media Center Edition";
+               osname = "XP Media Center Edition";
              else if (GetSystemMetrics (SM_TABLETPC))
-               osname = "XP Tablet PC Edition";
+               osname = "XP Tablet PC Edition";
              else if (!more_info)
                osname = "XP";
              else if (osversionex.wSuiteMask & VER_SUITE_PERSONAL)
-               osname = "XP Home Edition";
+               osname = "XP Home Edition";
              else
-               osname = "XP Professional";
+               osname = "XP Professional";
            }
          else if (osversion.dwMinorVersion == 2)
            {
@@ -1238,12 +1284,12 @@ dump_sysinfo ()
   if (wow64_func && wow64_func (GetCurrentProcess (), &is_wow64) && is_wow64)
     {
       void (WINAPI *nativinfo) (LPSYSTEM_INFO) = (void (WINAPI *)
-        (LPSYSTEM_INFO)) GetProcAddress (k32, "GetNativeSystemInfo");
+       (LPSYSTEM_INFO)) GetProcAddress (k32, "GetNativeSystemInfo");
       SYSTEM_INFO natinfo;
       nativinfo (&natinfo);
       fputs ("\nRunning under WOW64 on ", stdout);
       switch (natinfo.wProcessorArchitecture)
-        {
+       {
          case PROCESSOR_ARCHITECTURE_IA64:
            puts ("IA64");
            break;
@@ -1522,8 +1568,6 @@ dump_sysinfo ()
     }
   printf ("\n");
 
-  add_path ((char *) "\\bin", 4);      /* just in case */
-
   if (givehelp)
     printf
       ("Looking to see where common programs can be found, if at all...\n");
@@ -1540,10 +1584,10 @@ dump_sysinfo ()
   if (givehelp)
     printf ("Looking for various Cygwin DLLs...  (-v gives version info)\n");
   int cygwin_dll_count = 0;
-  for (i = 1; i < num_paths; i++)
+  for (pathlike *pth = paths; pth->dir; pth++)
     {
       WIN32_FIND_DATA ffinfo;
-      sprintf (tmp, "%s/*.*", paths[i]);
+      sprintf (tmp, "%s*.*", pth->dir);
       HANDLE ff = FindFirstFile (tmp, &ffinfo);
       int found = (ff != INVALID_HANDLE_VALUE);
       found_cygwin_dll = NULL;
@@ -1554,7 +1598,7 @@ dump_sysinfo ()
            {
              if (strncasecmp (f, "cyg", 3) == 0)
                {
-                 sprintf (tmp, "%s\\%s", paths[i], f);
+                 sprintf (tmp, "%s%s", pth->dir, f);
                  if (strcasecmp (f, "cygwin1.dll") == 0)
                    {
                      cygwin_dll_count++;
@@ -1672,7 +1716,7 @@ static const char safe_chars[] = "$-_.+!*'(),";
 
 /* the URL to query.  */
 static const char base_url[] =
-        "http://cygwin.com/cgi-bin2/package-grep.cgi?text=1&grep=";
+       "http://cygwin.com/cgi-bin2/package-grep.cgi?text=1&grep=";
 
 /* Queries Cygwin web site for packages containing files matching a regexp.
    Return value is 1 if there was a problem, otherwise 0.  */
@@ -1687,7 +1731,7 @@ package_grep (char *search)
   if (!(hWinInet = LoadLibrary ("wininet.dll")))
     {
       fputs ("Unable to locate WININET.DLL.  This feature requires Microsoft "
-             "Internet Explorer v3 or later to function.\n", stderr);
+            "Internet Explorer v3 or later to function.\n", stderr);
       return 1;
     }
 
@@ -1696,25 +1740,25 @@ package_grep (char *search)
      and call GetProcAddress for each of them with the following macro.  */
 
   pInternetCloseHandle = (BOOL (WINAPI *) (HINTERNET))
-                            GetProcAddress (hWinInet, "InternetCloseHandle");
+                           GetProcAddress (hWinInet, "InternetCloseHandle");
 #define make_func_pointer(name, ret, args) ret (WINAPI * p##name) args = \
-            (ret (WINAPI *) args) GetProcAddress (hWinInet, #name);
+           (ret (WINAPI *) args) GetProcAddress (hWinInet, #name);
   make_func_pointer (InternetAttemptConnect, DWORD, (DWORD));
-  make_func_pointer (InternetOpenA, HINTERNET, (LPCSTR, DWORD, LPCSTR, LPCSTR, 
-                                                DWORD));
-  make_func_pointer (InternetOpenUrlA, HINTERNET, (HINTERNET, LPCSTR, LPCSTR, 
-                                                   DWORD, DWORD, DWORD));
+  make_func_pointer (InternetOpenA, HINTERNET, (LPCSTR, DWORD, LPCSTR, LPCSTR,
+                                               DWORD));
+  make_func_pointer (InternetOpenUrlA, HINTERNET, (HINTERNET, LPCSTR, LPCSTR,
+                                                  DWORD, DWORD, DWORD));
   make_func_pointer (InternetReadFile, BOOL, (HINTERNET, PVOID, DWORD, PDWORD));
   make_func_pointer (HttpQueryInfoA, BOOL, (HINTERNET, DWORD, PVOID, PDWORD,
-                                            PDWORD));
+                                           PDWORD));
 #undef make_func_pointer
 
   if(!pInternetCloseHandle || !pInternetAttemptConnect || !pInternetOpenA
      || !pInternetOpenUrlA || !pInternetReadFile || !pHttpQueryInfoA)
     {
       fputs ("Unable to load one or more functions from WININET.DLL.  This "
-             "feature requires Microsoft Internet Explorer v3 or later to "
-             "function.\n", stderr);
+            "feature requires Microsoft Internet Explorer v3 or later to "
+            "function.\n", stderr);
       return 1;
     }
 
@@ -1726,16 +1770,16 @@ package_grep (char *search)
   for (dest = &url[sizeof (base_url) - 1]; *search; search++)
     {
       if (isalnum (*search)
-          || memchr (safe_chars, *search, sizeof (safe_chars) - 1))
-        {
-          *dest++ = *search;
-        }
+         || memchr (safe_chars, *search, sizeof (safe_chars) - 1))
+       {
+         *dest++ = *search;
+       }
       else
-        {
-          *dest++ = '%';
-          sprintf (dest, "%02x", (unsigned char) *search);
-          dest += 2;
-        }
+       {
+         *dest++ = '%';
+         sprintf (dest, "%02x", (unsigned char) *search);
+         dest += 2;
+       }
     }
   *dest = 0;
 
@@ -1753,18 +1797,18 @@ package_grep (char *search)
 
   if (!(hurl = pInternetOpenUrlA (hi, url, NULL, 0, 0, 0)))
     return display_internet_error ("unable to contact cygwin.com site, "
-                                   "InternetOpenUrl() failed", hi, NULL);
+                                  "InternetOpenUrl() failed", hi, NULL);
 
   /* Check the HTTP response code.  */
   DWORD rc = 0, rc_s = sizeof (DWORD);
   if (!pHttpQueryInfoA (hurl, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,
-                      (void *) &rc, &rc_s, NULL))
+                     (void *) &rc, &rc_s, NULL))
     return display_internet_error ("HttpQueryInfo() failed", hurl, hi, NULL);
 
   if (rc != HTTP_STATUS_OK)
     {
       sprintf (buf, "error retrieving results from cygwin.com site, "
-                    "HTTP status code %lu", rc);
+                   "HTTP status code %lu", rc);
       return display_internet_error (buf, hurl, hi, NULL);
     }
 
@@ -1773,9 +1817,9 @@ package_grep (char *search)
   do
     {
       if (!pInternetReadFile (hurl, (void *) buf, sizeof (buf), &numread))
-        return display_internet_error ("InternetReadFile failed", hurl, hi, NULL);
+       return display_internet_error ("InternetReadFile failed", hurl, hi, NULL);
       if (numread)
-        fwrite ((void *) buf, (size_t) numread, 1, stdout);
+       fwrite ((void *) buf, (size_t) numread, 1, stdout);
     }
   while (numread);
 
@@ -1955,8 +1999,8 @@ main (int argc, char **argv)
        list_package = 1;
        break;
       case 'p':
-        grep_packages = 1;
-        break;
+       grep_packages = 1;
+       break;
       case 'h':
        givehelp = 1;
        break;
index 356a60f..7559028 100644 (file)
@@ -1,6 +1,6 @@
 /* path.cc
 
-   Copyright 2001, 2002, 2003, 2005 Red Hat, Inc.
+   Copyright 2001, 2002, 2003, 2005, 2006, 2007 Red Hat, Inc.
 
 This file is part of Cygwin.
 
@@ -24,7 +24,7 @@ details. */
 #include "cygwin/include/mntent.h"
 
 /* Used when treating / and \ as equivalent. */
-#define SLASH_P(ch) \
+#define isslash(ch) \
   ({ \
       char __c = (ch); \
       ((__c) == '/' || (__c) == '\\'); \
@@ -150,7 +150,7 @@ is_symlink (HANDLE fh)
       if (got != size || !cmp_shortcut_header ((win_shortcut_hdr *) buf))
        return false; /* Not a Cygwin symlink. */
       /* TODO: check for invalid path contents
-         (see symlink_info::check() in ../cygwin/path.cc) */
+        (see symlink_info::check() in ../cygwin/path.cc) */
     }
   else /* magic == SYMLINK_MAGIC */
     {
@@ -161,7 +161,7 @@ is_symlink (HANDLE fh)
       if (!ReadFile (fh, buf, sizeof (buf), &got, 0))
        return false;
       if (got != sizeof (buf) ||
-          memcmp (buf, SYMLINK_COOKIE, sizeof (buf)) != 0)
+         memcmp (buf, SYMLINK_COOKIE, sizeof (buf)) != 0)
        return false; /* Not a Cygwin symlink. */
     }
   return true;
@@ -184,11 +184,11 @@ readlink (HANDLE fh, char *path, int maxlen)
          return false;
        }
       if (SetFilePointer (fh, 0x4c + offset + 4, 0, FILE_BEGIN) ==
-          INVALID_SET_FILE_POINTER && GetLastError () != NO_ERROR)
-        return false;
+         INVALID_SET_FILE_POINTER && GetLastError () != NO_ERROR)
+       return false;
 
       if (!ReadFile (fh, path, slen, (DWORD *) &got, 0))
-        return false;
+       return false;
       else if (got < slen)
        {
          SetLastError (ERROR_READ_FAULT);
@@ -203,15 +203,15 @@ readlink (HANDLE fh, char *path, int maxlen)
 
       if (SetFilePointer (fh, 0, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER
          && GetLastError () != NO_ERROR)
-        return false;
+       return false;
 
       if (!ReadFile (fh, cookie_buf, sizeof (cookie_buf), (DWORD *) &got, 0))
-        return false;
+       return false;
       else if (got == sizeof (cookie_buf)
               && memcmp (cookie_buf, SYMLINK_COOKIE, sizeof (cookie_buf)) == 0)
        {
          if (!ReadFile (fh, path, maxlen, (DWORD *) &got, 0))
-            return false;
+           return false;
          else if (got >= maxlen)
            {
              SetLastError (ERROR_FILENAME_EXCED_RANGE);
@@ -378,16 +378,16 @@ static int
 path_prefix_p (const char *path1, const char *path2, int len1)
 {
   /* Handle case where PATH1 has trailing '/' and when it doesn't.  */
-  if (len1 > 0 && SLASH_P (path1[len1 - 1]))
+  if (len1 > 0 && isslash (path1[len1 - 1]))
     len1--;
 
   if (len1 == 0)
-    return SLASH_P (path2[0]) && !SLASH_P (path2[1]);
+    return isslash (path2[0]) && !isslash (path2[1]);
 
   if (strncasecmp (path1, path2, len1) != 0)
     return 0;
 
-  return SLASH_P (path2[len1]) || path2[len1] == 0 || path1[len1 - 1] == ':';
+  return isslash (path2[len1]) || path2[len1] == 0 || path1[len1 - 1] == ':';
 }
 
 static char *
@@ -403,7 +403,7 @@ vconcat (const char *s, va_list v)
 
   len = strlen (s);
 
-  unc = SLASH_P (*s) && SLASH_P (s[1]);
+  unc = isslash (*s) && isslash (s[1]);
 
   while (1)
     {
@@ -462,6 +462,43 @@ concat (const char *s, ...)
   return vconcat (s, v);
 }
 
+static char *
+rel_vconcat (const char *s, va_list v)
+{
+  char path[MAX_PATH + 1];
+  if (!GetCurrentDirectory (MAX_PATH, path))
+    return NULL;
+
+  int max_len = -1;
+  struct mnt *m, *match = NULL;
+
+  if (s[0] == '.' && isslash (s[1]))
+    s += 2;
+
+  for (m = mount_table; m->posix ; m++)
+    {
+      if (m->flags & MOUNT_CYGDRIVE)
+       continue;
+
+      int n = strlen (m->native);
+      if (n < max_len || !path_prefix_p (m->native, path, n))
+       continue;
+      max_len = n;
+      match = m;
+    }
+
+  if (match)
+    strcpy (path, match->posix);
+
+  if (!isslash (strchr (path, '\0')[-1]))
+    strcat (path, "/");
+
+  char *temppath = concat (path, s, NULL);
+  char *res = vconcat (temppath, v);
+  free (temppath);
+  return res;
+}
+
 char *
 cygpath (const char *s, ...)
 {
@@ -472,9 +509,15 @@ cygpath (const char *s, ...)
   if (!mount_table[0].posix)
     read_mounts ();
   va_start (v, s);
-  char *path = vconcat (s, v);
-  if (strncmp (path, "./", 2) == 0)
-    memmove (path, path + 2, strlen (path + 2) + 1);
+  char *path;
+  if (s[0] == '/' || s[1] == ':')      /* FIXME: too crude? */
+    path = vconcat (s, v);
+  else
+    path = rel_vconcat (s, v);
+
+  if (!path)
+    return NULL;
+
   if (strncmp (path, "/./", 3) == 0)
     memmove (path + 1, path + 3, strlen (path + 3) + 1);
 
@@ -542,7 +585,7 @@ getmntent (FILE *)
     strcat (mnt.mnt_opts, (char *) ",noexec");
   if (m->flags & MOUNT_ENC)
     strcat (mnt.mnt_opts, ",managed");
-  if ((m->flags & MOUNT_CYGDRIVE))             /* cygdrive */
+  if ((m->flags & MOUNT_CYGDRIVE))     /* cygdrive */
     strcat (mnt.mnt_opts, (char *) ",cygdrive");
   mnt.mnt_freq = 1;
   mnt.mnt_passno = 1;