3 Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
4 2006, 2007, 2008 Red Hat, Inc.
6 This file is part of Cygwin.
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
12 #define cygwin_internal cygwin_internal_dontuse
24 #include "cygwin/include/sys/cygwin.h"
25 #include "cygwin/include/mntent.h"
26 #undef cygwin_internal
28 #define alloca __builtin_alloca
39 int grep_packages = 0;
41 static char emptystr[] = "";
43 /* This is global because it's used in both internet_display_error as well
45 BOOL (WINAPI *pInternetCloseHandle) (HINTERNET);
48 typedef long long longlong;
50 typedef __int64 longlong;
53 /* In dump_setup.cc */
54 void dump_setup (int, char **, bool);
55 void package_find (int, char **);
56 void package_list (int, char **);
58 void dump_dodgy_apps (int verbose);
61 static const char version[] = "$Revision$";
63 static const char *known_env_vars[] = {
71 "gcc_default_options",
93 static common_apps[] = {
122 static int num_paths, max_paths;
127 void pathlike::check_existence (const char *fn, int showall, int verbose,
128 char* first, const char *ext1 = "",
129 const char *ext2 = "");
133 int first_nonsys_path;
136 eprintf (const char *format, ...)
139 va_start (ap, format);
140 vfprintf (stderr, format, ap);
145 * display_error() is used to report failure modes
148 display_error (const char *name, bool show_error, bool print_failed)
150 fprintf (stderr, "cygcheck: %s", name);
152 fprintf (stderr, "%s: %lu\n",
153 print_failed ? " failed" : "", GetLastError ());
155 fprintf (stderr, "%s\n",
156 print_failed ? " failed" : "");
161 display_error (const char *name)
163 return display_error (name, true, true);
167 display_error (const char *fmt, const char *x)
170 sprintf (buf, fmt, x);
171 return display_error (buf, false, false);
175 display_error_fmt (const char *fmt, ...)
181 vsprintf (buf, fmt, va);
182 return display_error (buf, false, false);
185 /* Display a WinInet error message, and close a variable number of handles.
186 (Passed a list of handles terminated by NULL.) */
188 display_internet_error (const char *message, ...)
190 DWORD err = GetLastError ();
195 /* in the case of a successful connection but 404 response, there is no
196 win32 error message, but we still get passed a message to display. */
199 if (FormatMessage (FORMAT_MESSAGE_FROM_HMODULE,
200 GetModuleHandle ("wininet.dll"), err, 0, err_buf,
201 sizeof (err_buf), NULL) == 0)
202 strcpy (err_buf, "(Unknown error)");
204 fprintf (stderr, "cygcheck: %s: %s (win32 error %d)\n", message,
208 fprintf (stderr, "cygcheck: %s\n", message);
210 va_start (hptr, message);
211 while ((h = va_arg (hptr, HINTERNET)) != 0)
212 pInternetCloseHandle (h);
219 add_path (char *s, int maxlen, bool issys)
221 if (num_paths >= max_paths)
224 /* Extend path array */
225 paths = (pathlike *) realloc (paths, (1 + max_paths) * sizeof (paths[0]));
228 pathlike *pth = paths + num_paths;
230 /* Allocate space for directory in path list */
231 char *dir = (char *) calloc (maxlen + 2, sizeof (char));
234 display_error ("add_path: calloc() failed");
238 /* Copy input directory to path list */
239 memcpy (dir, s, maxlen);
241 /* Add a trailing slash by default */
242 char *e = strchr (dir, '\0');
243 if (e != dir && e[-1] != '\\')
246 /* Fill out this element */
257 add_path ((char *) ".", 1, true); /* to be replaced later */
259 if (GetCurrentDirectory (4000, tmp))
260 add_path (tmp, strlen (tmp), true);
262 display_error ("init_paths: GetCurrentDirectory()");
264 if (GetSystemDirectory (tmp, 4000))
265 add_path (tmp, strlen (tmp), true);
267 display_error ("init_paths: GetSystemDirectory()");
268 sl = strrchr (tmp, '\\');
271 strcpy (sl, "\\SYSTEM");
272 add_path (tmp, strlen (tmp), true);
274 GetWindowsDirectory (tmp, 4000);
275 add_path (tmp, strlen (tmp), true);
277 char *wpath = getenv ("PATH");
279 display_error ("WARNING: PATH is not set\n", "");
286 for (e = b; *e && *e != ';'; e++)
287 continue; /* loop terminates at first ';' or EOS */
288 if (strncmp(b, ".\\", 2) != 0)
289 add_path (b, e - b, false);
297 #define LINK_EXTENSION ".lnk"
300 pathlike::check_existence (const char *fn, int showall, int verbose,
301 char* first, const char *ext1, const char *ext2)
309 if (GetFileAttributes (file) != (DWORD) - 1)
311 char *lastdot = strrchr (file, '.');
312 bool is_link = lastdot && !strcmp (lastdot, LINK_EXTENSION);
313 // If file is a link, fix up the extension before printing
317 printf ("Found: %s\n", file);
318 if (verbose && *first != '\0' && strcasecmp (first, file) != 0)
320 char *flastdot = strrchr (first, '.');
321 bool f_is_link = flastdot && !strcmp (flastdot, LINK_EXTENSION);
322 // if first is a link, fix up the extension before printing
325 printf ("Warning: %s hides %s\n", first, file);
332 strcpy (first, file);
337 find_on_path (const char *in_file, const char *ext, bool showall = false,
338 bool search_sys = false, bool checklinks = false)
340 static char rv[4000];
342 /* Sort of a kludge but we've already tested this once, so don't try it again */
346 static pathlike abspath[2] =
355 display_error ("internal error find_on_path: NULL pointer for file", false, false);
361 display_error ("internal error find_on_path: NULL pointer for default_extension", false, false);
366 pathlike *search_paths;
367 if (!strpbrk (in_file, ":/\\"))
370 search_paths = paths;
374 file = cygpath (in_file, NULL);
375 search_paths = abspath;
381 display_error ("internal error find_on_path: cygpath conversion failed for %s\n", in_file);
385 char *hasext = strrchr (file, '.');
386 if (hasext && !strpbrk (hasext, "/\\"))
389 for (pathlike *pth = search_paths; pth->dir; pth++)
390 if (!pth->issys || search_sys)
392 pth->check_existence (file, showall, verbose, rv, ext);
395 pth->check_existence (file, showall, verbose, rv, ext, LINK_EXTENSION);
400 pth->check_existence (file, showall, verbose, rv);
402 pth->check_existence (file, showall, verbose, rv, LINK_EXTENSION);
405 return *rv ? rv : NULL;
410 #define DID_INACTIVE 3
421 already_did (const char *file)
424 for (d = did; d; d = d->next)
425 if (strcasecmp (d->file, file) == 0)
427 d = (Did *) malloc (sizeof (Did));
428 d->file = strdup (file);
440 int size_of_raw_data;
441 int pointer_to_raw_data;
445 rva_to_offset (int rva, char *sections, int nsections, int *sz)
449 if (sections == NULL)
451 display_error ("rva_to_offset: NULL passed for sections", true, false);
455 for (i = 0; i < nsections; i++)
457 Section *s = (Section *) (sections + i * 40);
459 printf ("%08x < %08x < %08x ? %08x\n",
460 s->virtual_address, rva,
461 s->virtual_address + s->virtual_size, s->pointer_to_raw_data);
463 if (rva >= s->virtual_address
464 && rva < s->virtual_address + s->virtual_size)
467 *sz = s->virtual_address + s->virtual_size - rva;
468 return rva - s->virtual_address + s->pointer_to_raw_data;
485 unsigned characteristics;
487 unsigned forwarder_chain;
492 static bool track_down (const char *file, const char *suffix, int lvl);
494 #define CYGPREFIX (sizeof ("%%% Cygwin ") - 1)
496 cygwin_info (HANDLE h)
498 char *buf, *bufend, *buf_start = NULL;
499 const char *hello = " Cygwin DLL version info:\n";
500 DWORD size = GetFileSize (h, NULL);
503 if (size == 0xffffffff)
506 buf_start = buf = (char *) calloc (1, size + 1);
509 display_error ("cygwin_info: calloc()");
513 (void) SetFilePointer (h, 0, NULL, FILE_BEGIN);
514 if (!ReadFile (h, buf, size, &n, NULL))
520 static char dummy[] = "\0\0\0\0\0\0\0";
521 char *dll_major = dummy;
524 if ((buf = (char *) memchr (buf, '%', bufend - buf)) == NULL)
526 else if (strncmp ("%%% Cygwin ", buf, CYGPREFIX) != 0)
530 char *p = strchr (buf += CYGPREFIX, '\n');
533 if (strncasecmp (buf, "dll major:", 10) == 0)
535 dll_major = buf + 11;
541 if (strncasecmp (buf, "dll minor:", 10) != 0)
545 char c = dll_major[1];
547 int maj = atoi (dll_major);
549 int min = atoi (dll_major + 1);
550 sprintf (pbuf, "DLL version: %d.%d.%.*s", maj, min, len - 11,
552 len = strlen (s = pbuf);
554 if (strncmp (s, "dll", 3) == 0)
555 memcpy (s, "DLL", 3);
556 else if (strncmp (s, "api", 3) == 0)
557 memcpy (s, "API", 3);
558 else if (islower (*s))
560 fprintf (stdout, "%s %.*s", hello, len, s);
572 dll_info (const char *path, HANDLE fh, int lvl, int recurse)
576 int pe_header_offset = get_dword (fh, 0x3c);
577 if (GetLastError () != NO_ERROR)
578 display_error ("get_dword");
579 int opthdr_ofs = pe_header_offset + 4 + 20;
584 display_error ("dll_info: NULL passed for path", true, false);
588 if (SetFilePointer (fh, opthdr_ofs + 40, 0, FILE_BEGIN) ==
589 INVALID_SET_FILE_POINTER && GetLastError () != NO_ERROR)
590 display_error ("dll_info: SetFilePointer()");
592 if (!ReadFile (fh, &v, sizeof (v), &junk, 0))
593 display_error ("dll_info: Readfile()");
596 printf (" - os=%d.%d img=%d.%d sys=%d.%d\n",
597 v[0], v[1], v[2], v[3], v[4], v[5]);
601 int num_entries = get_dword (fh, opthdr_ofs + 92);
602 if (GetLastError () != NO_ERROR)
603 display_error ("get_dword");
604 int export_rva = get_dword (fh, opthdr_ofs + 96);
605 if (GetLastError () != NO_ERROR)
606 display_error ("get_dword");
607 int export_size = get_dword (fh, opthdr_ofs + 100);
608 if (GetLastError () != NO_ERROR)
609 display_error ("get_dword");
610 int import_rva = get_dword (fh, opthdr_ofs + 104);
611 if (GetLastError () != NO_ERROR)
612 display_error ("get_dword");
613 int import_size = get_dword (fh, opthdr_ofs + 108);
614 if (GetLastError () != NO_ERROR)
615 display_error ("get_dword");
617 int nsections = get_word (fh, pe_header_offset + 4 + 2);
619 display_error ("get_word");
620 char *sections = (char *) malloc (nsections * 40);
622 if (SetFilePointer (fh, pe_header_offset + 4 + 20 +
623 get_word (fh, pe_header_offset + 4 + 16), 0,
624 FILE_BEGIN) == INVALID_SET_FILE_POINTER
625 && GetLastError () != NO_ERROR)
626 display_error ("dll_info: SetFilePointer()");
628 if (!ReadFile (fh, sections, nsections * 40, &junk, 0))
629 display_error ("dll_info: Readfile()");
631 if (verbose && num_entries >= 1 && export_size > 0)
634 int expbase = rva_to_offset (export_rva, sections, nsections, &expsz);
638 if (SetFilePointer (fh, expbase, 0, FILE_BEGIN) ==
639 INVALID_SET_FILE_POINTER && GetLastError () != NO_ERROR)
640 display_error ("dll_info: SetFilePointer()");
642 unsigned char *exp = (unsigned char *) malloc (expsz);
644 if (!ReadFile (fh, exp, expsz, &junk, 0))
645 display_error ("dll_info: Readfile()");
647 ExpDirectory *ed = (ExpDirectory *) exp;
648 int ofs = ed->name_rva - export_rva;
649 struct tm *tm = localtime ((const time_t *) &(ed->timestamp));
650 if (tm->tm_year < 60)
652 if (tm->tm_year < 200)
654 printf ("%*c", lvl + 2, ' ');
655 printf ("\"%s\" v%d.%d ts=", exp + ofs,
656 ed->major_ver, ed->minor_ver);
657 printf ("%d/%d/%d %d:%02d\n",
658 tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
659 tm->tm_hour, tm->tm_min);
663 if (num_entries >= 2 && import_size > 0 && recurse)
666 int impbase = rva_to_offset (import_rva, sections, nsections, &impsz);
669 if (SetFilePointer (fh, impbase, 0, FILE_BEGIN) ==
670 INVALID_SET_FILE_POINTER && GetLastError () != NO_ERROR)
671 display_error ("dll_info: SetFilePointer()");
673 unsigned char *imp = (unsigned char *) malloc (impsz);
676 display_error ("dll_info: malloc()");
680 if (!ReadFile (fh, imp, impsz, &junk, 0))
681 display_error ("dll_info: Readfile()");
683 ImpDirectory *id = (ImpDirectory *) imp;
684 for (i = 0; id[i].name_rva; i++)
686 /* int ofs = id[i].name_rva - import_rva; */
687 track_down ((char *) imp + id[i].name_rva - import_rva,
688 (char *) ".dll", lvl + 2);
692 if (strstr (path, "\\cygwin1.dll"))
696 // Return true on success, false if error printed
698 track_down (const char *file, const char *suffix, int lvl)
702 display_error ("track_down: NULL passed for file", true, false);
708 display_error ("track_down: NULL passed for suffix", false, false);
712 const char *path = find_on_path (file, suffix, false, true);
715 display_error ("track_down: could not find %s\n", file);
719 Did *d = already_did (file);
728 printf ("%*c", lvl, ' ');
730 printf (" (recursive)\n");
737 printf ("%*c", lvl, ' ');
739 printf (" (already done)\n");
747 printf ("%*c", lvl, ' ');
751 display_error ("file not found - '%s'\n", file);
758 CreateFile (path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
759 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
760 if (fh == INVALID_HANDLE_VALUE)
762 display_error ("cannot open - '%s'\n", path);
766 d->state = DID_ACTIVE;
769 dll_info (path, fh, lvl, 1);
770 else if (is_symlink (fh))
771 display_error ("%s is a symlink instead of a DLL\n", path);
774 int magic = get_word (fh, 0x0);
776 display_error ("get_word");
778 display_error_fmt ("%s is not a DLL: magic number %x (%d) '%s'\n",
779 path, magic, magic, (char *)&magic);
782 d->state = DID_INACTIVE;
783 if (!CloseHandle (fh))
784 display_error ("track_down: CloseHandle()");
791 HANDLE h = CreateFile (f, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
792 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
793 BY_HANDLE_FILE_INFORMATION info;
795 if (!GetFileInformationByHandle (h, &info))
796 display_error ("ls: GetFileInformationByHandle()");
800 if (!FileTimeToSystemTime (&info.ftLastWriteTime, &systime))
801 display_error ("ls: FileTimeToSystemTime()");
802 printf ("%5dk %04d/%02d/%02d %s",
803 (((int) info.nFileSizeLow) + 512) / 1024,
804 systime.wYear, systime.wMonth, systime.wDay, f);
805 dll_info (f, h, 16, 0);
806 if (!CloseHandle (h))
807 display_error ("ls: CloseHandle()");
810 /* Remove filename from 's' and return directory name without trailing
811 backslash, or NULL if 's' doesn't seem to have a dirname. */
813 dirname (const char *s)
815 static char buf[MAX_PATH];
820 strncpy (buf, s, MAX_PATH);
821 buf[MAX_PATH - 1] = '\0'; // in case strlen(s) > MAX_PATH
822 char *lastsep = strrchr (buf, '\\');
824 return NULL; // no backslash -> no dirname
825 else if (lastsep - buf <= 2 && buf[1] == ':')
826 lastsep[1] = '\0'; // can't remove backslash of "x:\"
832 // Find a real application on the path (possibly following symlinks)
834 find_app_on_path (const char *app, bool showall = false)
836 const char *papp = find_on_path (app, ".exe", showall, false, true);
839 CreateFile (papp, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
840 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
841 if (fh == INVALID_HANDLE_VALUE)
846 static char tmp[SYMLINK_MAX + 1];
847 if (!readlink (fh, tmp, SYMLINK_MAX))
848 display_error("readlink failed");
850 /* Resolve the linkname relative to the directory of the link. */
851 char *ptr = cygpath_rel (dirname (papp), tmp, NULL);
852 printf (" -> %s\n", ptr);
853 if (!strchr (ptr, '\\'))
856 strncpy (tmp, cygpath (papp, NULL), SYMLINK_MAX);
857 lastsep = strrchr (tmp, '\\');
858 strncpy (lastsep+1, ptr, SYMLINK_MAX - (lastsep-tmp));
861 if (!CloseHandle (fh))
862 display_error ("find_app_on_path: CloseHandle()");
863 /* FIXME: We leak the ptr returned by cygpath() here which is a
865 return find_app_on_path (ptr, showall);
868 if (!CloseHandle (fh))
869 display_error ("find_app_on_path: CloseHandle()");
873 // Return true on success, false if error printed
875 cygcheck (const char *app)
877 const char *papp = find_app_on_path (app, 1);
880 display_error ("could not find '%s'\n", app);
885 char *sep = strpbrk (papp, ":/\\");
888 static char dot[] = ".";
894 s = (char *) malloc (n + 2);
895 memcpy ((char *) s, papp, n);
896 strcpy (s + n, "\\");
901 return track_down (papp, ".exe", 0);
905 extern char **environ;
915 show_reg (RegInfo * ri, int nest)
919 show_reg (ri->prev, 1);
921 printf ("%s\\", ri->name);
923 printf ("%s\n", ri->name);
927 scan_registry (RegInfo * prev, HKEY hKey, char *name, int cygnus)
935 for (cp = name; *cp; cp++)
936 if (strncasecmp (cp, "cygnus", 6) == 0)
939 DWORD num_subkeys, max_subkey_len, num_values;
940 DWORD max_value_len, max_valdata_len, i;
941 if (RegQueryInfoKey (hKey, 0, 0, 0, &num_subkeys, &max_subkey_len, 0,
942 &num_values, &max_value_len, &max_valdata_len, 0, 0)
947 FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError (),
948 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), tmp, 400, 0);
949 printf ("RegQueryInfoKey: %s\n", tmp);
958 char *value_name = (char *) malloc (max_value_len + 1);
959 if (value_name == NULL)
961 display_error ("scan_registry: malloc()");
965 char *value_data = (char *) malloc (max_valdata_len + 1);
966 if (value_data == NULL)
968 display_error ("scan_registry: malloc()");
972 for (i = 0; i < num_values; i++)
974 DWORD dlen = max_valdata_len + 1;
975 DWORD nlen = max_value_len + 1;
977 RegEnumValue (hKey, i, value_name, &nlen, 0,
978 &type, (BYTE *) value_data, &dlen);
980 printf (" %s = ", i ? value_name : "(default)");
984 printf ("0x%08x\n", *(unsigned *) value_data);
988 printf ("'%s'\n", value_data);
991 printf ("(unsupported type)\n");
1000 char *subkey_name = (char *) malloc (max_subkey_len + 1);
1001 for (i = 0; i < num_subkeys; i++)
1003 if (RegEnumKey (hKey, i, subkey_name, max_subkey_len + 1) ==
1007 if (RegOpenKeyEx (hKey, subkey_name, 0, KEY_READ, &sKey)
1010 scan_registry (&ri, sKey, subkey_name, cygnus);
1011 if (RegCloseKey (sKey) != ERROR_SUCCESS)
1012 display_error ("scan_registry: RegCloseKey()");
1020 pretty_id (const char *s, char *cygwin, size_t cyglen)
1022 char *groups[16384];
1024 strcpy (cygwin + cyglen++, " ");
1025 strcpy (cygwin + cyglen, s);
1028 char *id = cygpath ("/bin/id.exe", NULL);
1029 for (char *p = id; (p = strchr (p, '/')); p++)
1032 if (access (id, X_OK))
1034 fprintf (stderr, "'id' program not found\n");
1038 FILE *f = popen (id, "rt");
1042 fgets (buf, sizeof (buf), f);
1044 char *uid = strtok (buf, ")");
1046 uid += strlen ("uid=");
1049 fprintf (stderr, "garbled output from 'id' command - no uid= found\n");
1052 char *gid = strtok (NULL, ")");
1054 gid += strlen ("gid=") + 1;
1057 fprintf (stderr, "garbled output from 'id' command - no gid= found\n");
1061 char **ng = groups - 1;
1062 size_t len_uid = strlen ("UID: )") + strlen (uid);
1063 size_t len_gid = strlen ("GID: )") + strlen (gid);
1064 *++ng = groups[0] = (char *) alloca (len_uid + 1);
1065 *++ng = groups[1] = (char *) alloca (len_gid + 1);
1066 sprintf (groups[0], "UID: %s)", uid);
1067 sprintf (groups[1], "GID: %s)", gid);
1068 size_t sz = max (len_uid, len_gid);
1069 while ((*++ng = strtok (NULL, ",")))
1071 char *p = strchr (*ng, '\n');
1074 if (ng == groups + 2)
1075 *ng += strlen (" groups=");
1076 size_t len = strlen (*ng);
1082 printf ("\nOutput from %s (%s)\n", id, s);
1083 int n = 80 / (int) ++sz;
1084 int i = n > 2 ? n - 2 : 0;
1086 for (char **g = groups; g <= ng; g++)
1087 if ((g != ng) && (++i < n))
1088 printf ("%*s", sz, *g);
1096 /* This dumps information about each installed cygwin service, if cygrunsrv
1099 dump_sysinfo_services ()
1104 bool no_services = false;
1107 printf ("\nChecking for any Cygwin services... %s\n\n",
1108 verbose ? "" : "(use -v for more detail)");
1110 fputc ('\n', stdout);
1112 /* find the location of cygrunsrv.exe */
1113 char *cygrunsrv = cygpath ("/bin/cygrunsrv.exe", NULL);
1114 for (char *p = cygrunsrv; (p = strchr (p, '/')); p++)
1117 if (access (cygrunsrv, X_OK))
1119 puts ("Can't find the cygrunsrv utility, skipping services check.\n");
1123 /* check for a recent cygrunsrv */
1124 snprintf (buf, sizeof (buf), "%s --version", cygrunsrv);
1125 if ((f = popen (buf, "rt")) == NULL)
1127 printf ("Failed to execute '%s', skipping services check.\n", buf);
1131 int ret = fscanf (f, "cygrunsrv V%u.%u", &maj, &min);
1132 if (ferror (f) || feof (f) || ret == EOF || maj < 1 || min < 10)
1134 puts ("The version of cygrunsrv installed is too old to dump service info.\n");
1139 /* For verbose mode, just run cygrunsrv --list --verbose and copy output
1140 verbatim; otherwise run cygrunsrv --list and then cygrunsrv --query for
1142 snprintf (buf, sizeof (buf), (verbose ? "%s --list --verbose" : "%s --list"),
1144 if ((f = popen (buf, "rt")) == NULL)
1146 printf ("Failed to execute '%s', skipping services check.\n", buf);
1152 /* copy output to stdout */
1154 while (!feof (f) && !ferror (f))
1155 nchars += fwrite ((void *) buf, 1,
1156 fread ((void *) buf, 1, sizeof (buf), f), stdout);
1158 /* cygrunsrv outputs nothing if there are no cygwin services found */
1165 /* read the output of --list, and then run --query for each service */
1166 size_t nchars = fread ((void *) buf, 1, sizeof (buf) - 1, f);
1171 for (char *srv = strtok (buf, "\n"); srv; srv = strtok (NULL, "\n"))
1173 snprintf (buf2, sizeof (buf2), "%s --query %s", cygrunsrv, srv);
1174 if ((f = popen (buf2, "rt")) == NULL)
1176 printf ("Failed to execute '%s', skipping services check.\n", buf2);
1180 /* copy output to stdout */
1181 while (!feof (f) && !ferror (f))
1182 fwrite ((void *) buf2, 1,
1183 fread ((void *) buf2, 1, sizeof (buf2), f), stdout);
1190 /* inform the user if nothing found */
1192 puts ("No Cygwin services found.\n");
1201 char *found_cygwin_dll;
1203 bool more_info = true;
1206 printf ("\nCygwin Configuration Diagnostics\n");
1208 printf ("Current System Time: %s\n", ctime (&now));
1210 OSVERSIONINFOEX osversion;
1211 osversion.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
1212 if (!GetVersionEx (reinterpret_cast<LPOSVERSIONINFO>(&osversion)))
1215 osversion.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
1216 if (!GetVersionEx (reinterpret_cast<LPOSVERSIONINFO>(&osversion)))
1217 display_error ("dump_sysinfo: GetVersionEx()");
1220 HMODULE k32 = LoadLibrary ("kernel32.dll");
1222 switch (osversion.dwPlatformId)
1224 case VER_PLATFORM_WIN32s:
1225 strcpy (osname, "32s (not supported)");
1227 case VER_PLATFORM_WIN32_WINDOWS:
1228 strcpy (osname, "95/98/Me (not supported)");
1230 case VER_PLATFORM_WIN32_NT:
1232 if (osversion.dwMajorVersion == 6)
1234 BOOL (WINAPI *GetProductInfo) (DWORD, DWORD, DWORD, DWORD, PDWORD) =
1235 (BOOL (WINAPI *)(DWORD, DWORD, DWORD, DWORD, PDWORD))
1236 GetProcAddress (k32, "GetProductInfo");
1237 if (osversion.wProductType == VER_NT_WORKSTATION)
1238 strcpy (osname, "Vista");
1240 strcpy (osname, "2008");
1242 if (GetProductInfo (osversion.dwMajorVersion,
1243 osversion.dwMinorVersion,
1244 osversion.wServicePackMajor,
1245 osversion.wServicePackMinor,
1248 #define PRODUCT_UNLICENSED 0xabcdabcd
1249 #define PRODUCT_SMALLBUSINESS_SERVER_PREMIUM 0x19
1250 const char *products[] =
1253 " Ultimate Edition",
1254 " Home Basic Edition",
1255 " Home Premium Edition",
1256 " Enterprise Edition",
1257 " Home Basic N Edition",
1258 " Business Edition",
1259 " Server Standard Edition",
1260 " Server Datacenter Edition",
1261 " Small Business Server",
1262 " Server Enterprise Edition",
1264 " Server Datacenter Edition Core",
1265 " Server Standard Edition Core",
1266 " Server Enterprise Edition Core",
1267 " Server Enterprise Edition for Itanium-based Systems",
1268 " Business N Edition",
1269 " Web Server Edition",
1270 " Cluster Server Edition",
1271 " Home Server Edition",
1272 " Storage Server Express Edition",
1273 " Storage Server Standard Edition",
1274 " Storage Server Workgroup Edition",
1275 " Storage Server Enterprise Edition",
1276 " Server for Small Business Edition",
1277 " Small Business Server Premium Edition"
1279 if (prod == PRODUCT_UNLICENSED)
1280 strcat (osname, "Unlicensed");
1281 else if (prod > PRODUCT_SMALLBUSINESS_SERVER_PREMIUM)
1282 strcat (osname, "");
1284 strcat (osname, products[prod]);
1290 else if (osversion.dwMajorVersion == 5)
1292 if (osversion.dwMinorVersion == 0)
1294 strcpy (osname, "2000");
1295 if (osversion.wProductType == VER_NT_WORKSTATION)
1296 strcat (osname, " Professional");
1297 else if (osversion.wSuiteMask & VER_SUITE_DATACENTER)
1298 strcat (osname, " Datacenter Server");
1299 else if (osversion.wSuiteMask & VER_SUITE_ENTERPRISE)
1300 strcat (osname, " Advanced Server");
1302 strcat (osname, " Server");
1304 else if (osversion.dwMinorVersion == 1)
1306 strcpy (osname, "XP");
1307 if (GetSystemMetrics (SM_MEDIACENTER))
1308 strcat (osname, " Media Center Edition");
1309 else if (GetSystemMetrics (SM_TABLETPC))
1310 strcat (osname, " Tablet PC Edition");
1311 else if (GetSystemMetrics (SM_STARTER))
1312 strcat (osname, " Starter Edition");
1313 else if (osversion.wSuiteMask & VER_SUITE_PERSONAL)
1314 strcat (osname, " Home Edition");
1316 strcat (osname, " Professional");
1318 else if (osversion.dwMinorVersion == 2)
1320 strcpy (osname, "2003 Server");
1321 if (GetSystemMetrics (SM_SERVERR2))
1322 strcat (osname, " R2");
1323 if (osversion.wSuiteMask & VER_SUITE_BLADE)
1324 strcat (osname, " Web Edition");
1325 else if (osversion.wSuiteMask & VER_SUITE_DATACENTER)
1326 strcat (osname, " Datacenter Edition");
1327 else if (osversion.wSuiteMask & VER_SUITE_ENTERPRISE)
1328 strcat (osname, " Enterprise Edition");
1329 else if (osversion.wSuiteMask & VER_SUITE_COMPUTE_SERVER)
1330 strcat (osname, " Compute Cluster Edition");
1333 else if (osversion.dwMajorVersion == 4)
1335 strcpy (osname, "NT 4");
1338 if (osversion.wProductType == VER_NT_WORKSTATION)
1339 strcat (osname, " Workstation");
1342 strcat (osname, " Server");
1343 if (osversion.wSuiteMask & VER_SUITE_ENTERPRISE)
1344 strcat (osname, " Enterprise Edition");
1349 strcpy (osname, "NT");
1352 strcpy (osname, "??");
1355 printf ("Windows %s Ver %lu.%lu Build %lu %s\n", osname,
1356 osversion.dwMajorVersion, osversion.dwMinorVersion,
1357 osversion.dwPlatformId == VER_PLATFORM_WIN32_NT ?
1358 osversion.dwBuildNumber : (osversion.dwBuildNumber & 0xffff),
1359 osversion.dwPlatformId == VER_PLATFORM_WIN32_NT ?
1360 osversion.szCSDVersion : "");
1362 if (osversion.dwPlatformId == VER_PLATFORM_WIN32s
1363 || osversion.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
1364 exit (EXIT_FAILURE);
1366 BOOL (WINAPI *wow64_func) (HANDLE, PBOOL) = (BOOL (WINAPI *) (HANDLE, PBOOL))
1367 GetProcAddress (k32, "IsWow64Process");
1368 BOOL is_wow64 = FALSE;
1369 if (wow64_func && wow64_func (GetCurrentProcess (), &is_wow64) && is_wow64)
1371 void (WINAPI *nativinfo) (LPSYSTEM_INFO) = (void (WINAPI *)
1372 (LPSYSTEM_INFO)) GetProcAddress (k32, "GetNativeSystemInfo");
1373 SYSTEM_INFO natinfo;
1374 nativinfo (&natinfo);
1375 fputs ("\nRunning under WOW64 on ", stdout);
1376 switch (natinfo.wProcessorArchitecture)
1378 case PROCESSOR_ARCHITECTURE_IA64:
1381 case PROCESSOR_ARCHITECTURE_AMD64:
1390 if (GetSystemMetrics (SM_REMOTESESSION))
1391 printf ("\nRunning in Terminal Service session\n");
1394 char *s = getenv ("PATH"), *e;
1399 char sep = strchr (s, ';') ? ';' : ':';
1400 int count_path_items = 0;
1403 for (e = s; *e && *e != sep; e++);
1405 printf ("\t%.*s\n", e - s, s);
1417 char *cygwin = getenv ("CYGWIN");
1419 cygwin -= strlen ("CYGWIN=");
1421 cygwin = const_cast <char *> ("CYGWIN=");
1422 size_t cyglen = strlen (cygwin);
1423 cygwin = strcpy ((char *) malloc (cyglen + sizeof (" nontsec")), cygwin);
1424 pretty_id ("nontsec", cygwin, cyglen);
1425 pretty_id ("ntsec", cygwin, cyglen);
1429 if (!GetSystemDirectory (tmp, 4000))
1430 display_error ("dump_sysinfo: GetSystemDirectory()");
1431 printf ("\nSysDir: %s\n", tmp);
1433 GetWindowsDirectory (tmp, 4000);
1434 printf ("WinDir: %s\n\n", tmp);
1438 printf ("Here's some environment variables that may affect cygwin:\n");
1439 for (i = 0; environ[i]; i++)
1441 char *eq = strchr (environ[i], '=');
1444 /* int len = eq - environ[i]; */
1445 for (j = 0; known_env_vars[j]; j++)
1448 if (strcmp (environ[i], "PATH") == 0)
1449 continue; /* we handle this one specially */
1450 if (strcasecmp (environ[i], known_env_vars[j]) == 0)
1451 printf ("%s = '%s'\n", environ[i], eq + 1);
1460 printf ("Here's the rest of your environment variables:\n");
1461 for (i = 0; environ[i]; i++)
1464 char *eq = strchr (environ[i], '=');
1467 /* int len = eq - environ[i]; */
1468 for (j = 0; known_env_vars[j]; j++)
1471 if (strcasecmp (environ[i], known_env_vars[j]) == 0)
1478 printf ("%s = '%s'\n", environ[i], eq + 1);
1488 printf ("Scanning registry for keys with 'Cygnus' in them...\n");
1490 /* big and not generally useful */
1491 scan_registry (0, HKEY_CLASSES_ROOT, (char *) "HKEY_CLASSES_ROOT", 0);
1493 scan_registry (0, HKEY_CURRENT_CONFIG,
1494 (char *) "HKEY_CURRENT_CONFIG", 0);
1495 scan_registry (0, HKEY_CURRENT_USER, (char *) "HKEY_CURRENT_USER", 0);
1496 scan_registry (0, HKEY_LOCAL_MACHINE, (char *) "HKEY_LOCAL_MACHINE", 0);
1498 /* the parts we need are duplicated in HKEY_CURRENT_USER anyway */
1499 scan_registry (0, HKEY_USERS, (char *) "HKEY_USERS", 0);
1504 printf ("Use '-r' to scan registry\n\n");
1508 printf ("Listing available drives...\n");
1509 printf ("Drv Type Size Used Flags Name\n");
1512 SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
1513 int drivemask = GetLogicalDrives ();
1515 BOOL (WINAPI * gdfse) (LPCSTR, long long *, long long *, long long *) =
1516 (BOOL (WINAPI *) (LPCSTR, long long *, long long *, long long *))
1517 GetProcAddress (k32, "GetDiskFreeSpaceExA");
1519 for (i = 0; i < 26; i++)
1521 if (!(drivemask & (1 << i)))
1523 char drive[4], name[200], fsname[200];
1524 DWORD serno = 0, maxnamelen = 0, flags = 0;
1525 name[0] = name[0] = fsname[0] = 0;
1526 sprintf (drive, "%c:\\", i + 'a');
1527 /* Report all errors, except if the Volume is ERROR_NOT_READY.
1528 ERROR_NOT_READY is returned when removeable media drives are empty
1529 (CD, floppy, etc.) */
1530 if (!GetVolumeInformation (drive, name, sizeof (name), &serno,
1531 &maxnamelen, &flags, fsname,
1533 && GetLastError () != ERROR_NOT_READY)
1535 # define FMT "dump_sysinfo: GetVolumeInformation() for drive %c:"
1536 char buf[sizeof (FMT)];
1537 sprintf (buf, FMT, 'A' + i);
1538 display_error (buf);
1542 int dtype = GetDriveType (drive);
1543 char drive_type[4] = "unk";
1546 case DRIVE_REMOVABLE:
1547 strcpy (drive_type, "fd ");
1550 strcpy (drive_type, "hd ");
1553 strcpy (drive_type, "net");
1556 strcpy (drive_type, "cd ");
1559 strcpy (drive_type, "ram");
1562 strcpy (drive_type, "unk");
1565 long capacity_mb = -1;
1566 int percent_full = -1;
1568 long long free_me = 0ULL, free_bytes = 0ULL, total_bytes = 1ULL;
1569 if (gdfse != NULL && gdfse (drive, &free_me, &total_bytes, &free_bytes))
1571 capacity_mb = total_bytes / (1024L * 1024L);
1572 percent_full = 100 - (int) ((100.0 * free_me) / total_bytes);
1576 DWORD spc = 0, bps = 0, fc = 0, tc = 1;
1577 if (GetDiskFreeSpace (drive, &spc, &bps, &fc, &tc))
1579 capacity_mb = (spc * bps * tc) / (1024 * 1024);
1580 percent_full = 100 - (int) ((100.0 * fc) / tc);
1584 printf ("%.2s %s %-6s ", drive, drive_type, fsname);
1585 if (capacity_mb >= 0)
1586 printf ("%7dMb %3d%% ", (int) capacity_mb, (int) percent_full);
1588 printf (" N/A N/A ");
1589 printf ("%s %s %s %s %s %s %s\n",
1590 flags & FS_CASE_IS_PRESERVED ? "CP" : " ",
1591 flags & FS_CASE_SENSITIVE ? "CS" : " ",
1592 flags & FS_UNICODE_STORED_ON_DISK ? "UN" : " ",
1593 flags & FS_PERSISTENT_ACLS ? "PA" : " ",
1594 flags & FS_FILE_COMPRESSION ? "FC" : " ",
1595 flags & FS_VOL_IS_COMPRESSED ? "VC" : " ",
1597 flags & FILE_SUPPORTS_ENCRYPTION ? "EN" : " ",
1598 flags & FILE_SUPPORTS_OBJECT_IDS ? "OI" : " ",
1599 flags & FILE_SUPPORTS_REPARSE_POINTS ? "RP" : " ",
1600 flags & FILE_SUPPORTS_SPARSE_FILES ? "SP" : " ",
1601 flags & FILE_VOLUME_QUOTAS ? "QU" : " ",
1606 if (!FreeLibrary (k32))
1607 display_error ("dump_sysinfo: FreeLibrary()");
1608 SetErrorMode (prev_mode);
1612 "fd = floppy, hd = hard drive, cd = CD-ROM\n"
1613 "net= Network Share, ram= RAM drive, unk= Unknown\n"
1614 "CP = Case Preserving, CS = Case Sensitive, UN = Unicode\n"
1615 "PA = Persistent ACLS, FC = File Compression, VC = Volume Compression");
1619 unsigned ml_fsname = 4, ml_dir = 7, ml_type = 6;
1620 bool ml_trailing = false;
1624 while ((mnt = getmntent (0)))
1626 unsigned n = (int) strlen (mnt->mnt_fsname);
1627 ml_trailing |= (n > 1 && strchr ("\\/", mnt->mnt_fsname[n - 1]));
1630 n = (int) strlen (mnt->mnt_dir);
1631 ml_trailing |= (n > 1 && strchr ("\\/", mnt->mnt_dir[n - 1]));
1637 puts ("Warning: Mount entries should not have a trailing (back)slash\n");
1642 ("Mount entries: these map POSIX directories to your NT drives.\n");
1643 printf ("%-*s %-*s %-*s %s\n", ml_fsname, "-NT-", ml_dir, "-POSIX-",
1644 ml_type, "-Type-", "-Flags-");
1648 while ((mnt = getmntent (0)))
1650 printf ("%-*s %-*s %-*s %s\n",
1651 ml_fsname, mnt->mnt_fsname,
1652 ml_dir, mnt->mnt_dir, ml_type, mnt->mnt_type, mnt->mnt_opts);
1658 ("Looking to see where common programs can be found, if at all...\n");
1659 for (i = 0; common_apps[i].name; i++)
1660 if (!find_app_on_path ((char *) common_apps[i].name, 1))
1662 if (common_apps[i].missing_is_good)
1663 printf ("Not Found: %s (good!)\n", common_apps[i].name);
1665 printf ("Not Found: %s\n", common_apps[i].name);
1670 printf ("Looking for various Cygwin DLLs... (-v gives version info)\n");
1671 int cygwin_dll_count = 0;
1672 char cygdll_path[32768];
1673 for (pathlike *pth = paths; pth->dir; pth++)
1675 WIN32_FIND_DATA ffinfo;
1676 sprintf (tmp, "%s*.*", pth->dir);
1677 HANDLE ff = FindFirstFile (tmp, &ffinfo);
1678 int found = (ff != INVALID_HANDLE_VALUE);
1679 found_cygwin_dll = NULL;
1682 char *f = ffinfo.cFileName;
1683 if (strcasecmp (f + strlen (f) - 4, ".dll") == 0)
1685 if (strncasecmp (f, "cyg", 3) == 0)
1687 sprintf (tmp, "%s%s", pth->dir, f);
1688 if (strcasecmp (f, "cygwin1.dll") == 0)
1690 if (!cygwin_dll_count)
1691 strcpy (cygdll_path, pth->dir);
1692 if (!cygwin_dll_count
1693 || strcasecmp (cygdll_path, pth->dir) != 0)
1695 found_cygwin_dll = strdup (tmp);
1701 found = FindNextFile (ff, &ffinfo);
1703 if (found_cygwin_dll)
1705 ls (found_cygwin_dll);
1706 free (found_cygwin_dll);
1711 if (cygwin_dll_count > 1)
1712 puts ("Warning: There are multiple cygwin1.dlls on your path");
1713 if (!cygwin_dll_count)
1714 puts ("Warning: cygwin1.dll not found on your path");
1716 dump_dodgy_apps (verbose);
1719 dump_sysinfo_services ();
1725 HANDLE h = CreateFileA ("CONIN$", GENERIC_READ | GENERIC_WRITE,
1726 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1727 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1729 if (h == INVALID_HANDLE_VALUE || h == NULL)
1730 return (display_error ("check_keys: Opening CONIN$"));
1734 if (!GetConsoleMode (h, &mode))
1735 display_error ("check_keys: GetConsoleMode()");
1738 mode &= ~ENABLE_PROCESSED_INPUT;
1739 if (!SetConsoleMode (h, mode))
1740 display_error ("check_keys: SetConsoleMode()");
1743 fputs ("\nThis key check works only in a console window,", stderr);
1744 fputs (" _NOT_ in a terminal session!\n", stderr);
1745 fputs ("Abort with Ctrl+C if in a terminal session.\n\n", stderr);
1746 fputs ("Press 'q' to exit.\n", stderr);
1748 INPUT_RECORD in, prev_in;
1750 // Drop first <RETURN> key
1751 ReadConsoleInput (h, &in, 1, &mode);
1753 memset (&in, 0, sizeof in);
1758 if (!ReadConsoleInput (h, &in, 1, &mode))
1759 display_error ("check_keys: ReadConsoleInput()");
1761 if (!memcmp (&in, &prev_in, sizeof in))
1764 switch (in.EventType)
1767 printf ("%s %ux VK: 0x%02x VS: 0x%02x A: 0x%02x CTRL: ",
1768 in.Event.KeyEvent.bKeyDown ? "Pressed " : "Released",
1769 in.Event.KeyEvent.wRepeatCount,
1770 in.Event.KeyEvent.wVirtualKeyCode,
1771 in.Event.KeyEvent.wVirtualScanCode,
1772 (unsigned char) in.Event.KeyEvent.uChar.AsciiChar);
1773 fputs (in.Event.KeyEvent.dwControlKeyState & CAPSLOCK_ON ?
1774 "CL " : "-- ", stdout);
1775 fputs (in.Event.KeyEvent.dwControlKeyState & ENHANCED_KEY ?
1776 "EK " : "-- ", stdout);
1777 fputs (in.Event.KeyEvent.dwControlKeyState & LEFT_ALT_PRESSED ?
1778 "LA " : "-- ", stdout);
1779 fputs (in.Event.KeyEvent.dwControlKeyState & LEFT_CTRL_PRESSED ?
1780 "LC " : "-- ", stdout);
1781 fputs (in.Event.KeyEvent.dwControlKeyState & NUMLOCK_ON ?
1782 "NL " : "-- ", stdout);
1783 fputs (in.Event.KeyEvent.dwControlKeyState & RIGHT_ALT_PRESSED ?
1784 "RA " : "-- ", stdout);
1785 fputs (in.Event.KeyEvent.dwControlKeyState & RIGHT_CTRL_PRESSED ?
1786 "RC " : "-- ", stdout);
1787 fputs (in.Event.KeyEvent.dwControlKeyState & SCROLLLOCK_ON ?
1788 "SL " : "-- ", stdout);
1789 fputs (in.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED ?
1790 "SH " : "-- ", stdout);
1791 fputc ('\n', stdout);
1798 while (in.EventType != KEY_EVENT ||
1799 in.Event.KeyEvent.bKeyDown != FALSE ||
1800 in.Event.KeyEvent.uChar.AsciiChar != 'q');
1806 /* RFC1738 says that these do not need to be escaped. */
1807 static const char safe_chars[] = "$-_.+!*'(),";
1809 /* the URL to query. */
1810 static const char base_url[] =
1811 "http://cygwin.com/cgi-bin2/package-grep.cgi?text=1&grep=";
1813 /* Queries Cygwin web site for packages containing files matching a regexp.
1814 Return value is 1 if there was a problem, otherwise 0. */
1816 package_grep (char *search)
1820 /* Attempt to dynamically load the necessary WinInet API functions so that
1821 cygcheck can still function on older systems without IE. */
1823 if (!(hWinInet = LoadLibrary ("wininet.dll")))
1825 fputs ("Unable to locate WININET.DLL. This feature requires Microsoft "
1826 "Internet Explorer v3 or later to function.\n", stderr);
1830 /* InternetCloseHandle is used outside this function so it is declared
1831 global. The rest of these functions are only used here, so declare them
1832 and call GetProcAddress for each of them with the following macro. */
1834 pInternetCloseHandle = (BOOL (WINAPI *) (HINTERNET))
1835 GetProcAddress (hWinInet, "InternetCloseHandle");
1836 #define make_func_pointer(name, ret, args) ret (WINAPI * p##name) args = \
1837 (ret (WINAPI *) args) GetProcAddress (hWinInet, #name);
1838 make_func_pointer (InternetAttemptConnect, DWORD, (DWORD));
1839 make_func_pointer (InternetOpenA, HINTERNET, (LPCSTR, DWORD, LPCSTR, LPCSTR,
1841 make_func_pointer (InternetOpenUrlA, HINTERNET, (HINTERNET, LPCSTR, LPCSTR,
1842 DWORD, DWORD, DWORD));
1843 make_func_pointer (InternetReadFile, BOOL, (HINTERNET, PVOID, DWORD, PDWORD));
1844 make_func_pointer (HttpQueryInfoA, BOOL, (HINTERNET, DWORD, PVOID, PDWORD,
1846 #undef make_func_pointer
1848 if(!pInternetCloseHandle || !pInternetAttemptConnect || !pInternetOpenA
1849 || !pInternetOpenUrlA || !pInternetReadFile || !pHttpQueryInfoA)
1851 fputs ("Unable to load one or more functions from WININET.DLL. This "
1852 "feature requires Microsoft Internet Explorer v3 or later to "
1853 "function.\n", stderr);
1857 /* construct the actual URL by escaping */
1858 char *url = (char *) alloca (sizeof (base_url) + strlen (search) * 3);
1859 strcpy (url, base_url);
1862 for (dest = &url[sizeof (base_url) - 1]; *search; search++)
1864 if (isalnum (*search)
1865 || memchr (safe_chars, *search, sizeof (safe_chars) - 1))
1872 sprintf (dest, "%02x", (unsigned char) *search);
1878 /* Connect to the net and open the URL. */
1879 if (pInternetAttemptConnect (0) != ERROR_SUCCESS)
1881 fputs ("An internet connection is required for this function.\n", stderr);
1885 /* Initialize WinInet and attempt to fetch our URL. */
1886 HINTERNET hi = NULL, hurl = NULL;
1887 if (!(hi = pInternetOpenA ("cygcheck", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0)))
1888 return display_internet_error ("InternetOpen() failed", NULL);
1890 if (!(hurl = pInternetOpenUrlA (hi, url, NULL, 0, 0, 0)))
1891 return display_internet_error ("unable to contact cygwin.com site, "
1892 "InternetOpenUrl() failed", hi, NULL);
1894 /* Check the HTTP response code. */
1895 DWORD rc = 0, rc_s = sizeof (DWORD);
1896 if (!pHttpQueryInfoA (hurl, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,
1897 (void *) &rc, &rc_s, NULL))
1898 return display_internet_error ("HttpQueryInfo() failed", hurl, hi, NULL);
1900 if (rc != HTTP_STATUS_OK)
1902 sprintf (buf, "error retrieving results from cygwin.com site, "
1903 "HTTP status code %lu", rc);
1904 return display_internet_error (buf, hurl, hi, NULL);
1907 /* Fetch result and print to stdout. */
1911 if (!pInternetReadFile (hurl, (void *) buf, sizeof (buf), &numread))
1912 return display_internet_error ("InternetReadFile failed", hurl, hi, NULL);
1914 fwrite ((void *) buf, (size_t) numread, 1, stdout);
1918 pInternetCloseHandle (hurl);
1919 pInternetCloseHandle (hi);
1924 usage (FILE * stream, int status)
1927 Usage: cygcheck PROGRAM [ -v ] [ -h ]\n\
1928 cygcheck -c [ PACKAGE ] [ -d ]\n\
1929 cygcheck -s [ -r ] [ -v ] [ -h ]\n\
1931 cygcheck -f FILE [ FILE ... ]\n\
1932 cygcheck -l [ PACKAGE ] [ PACKAGE ... ]\n\
1933 cygcheck -p REGEXP\n\
1934 List system information, check installed packages, or query package database.\n\
1936 At least one command option or a PROGRAM is required, as shown above.\n\
1938 PROGRAM list library (DLL) dependencies of PROGRAM\n\
1939 -c, --check-setup show installed version of PACKAGE and verify integrity\n\
1940 (or for all installed packages if none specified)\n\
1941 -d, --dump-only just list packages, do not verify (with -c)\n\
1942 -s, --sysinfo produce diagnostic system information (implies -c -d)\n\
1943 -r, --registry also scan registry for Cygwin settings (with -s)\n\
1944 -k, --keycheck perform a keyboard check session (must be run from a\n\
1945 plain console only, not from a pty/rxvt/xterm)\n\
1946 -f, --find-package find the package that FILE belongs to\n\
1947 -l, --list-package list contents of PACKAGE (or all packages if none given)\n\
1948 -p, --package-query search for REGEXP in the entire cygwin.com package\n\
1949 repository (requies internet connectivity)\n\
1950 -v, --verbose produce more verbose output\n\
1951 -h, --help annotate output with explanatory comments when given\n\
1952 with another command, otherwise print this help\n\
1953 -V, --version print the version of cygcheck and exit\n\
1955 Note: -c, -f, and -l only report on packages that are currently installed. To\n\
1956 search all official Cygwin packages use -p instead. The -p REGEXP matches\n\
1957 package names, descriptions, and names of files/paths within all packages.\n\
1962 struct option longopts[] = {
1963 {"check-setup", no_argument, NULL, 'c'},
1964 {"dump-only", no_argument, NULL, 'd'},
1965 {"sysinfo", no_argument, NULL, 's'},
1966 {"registry", no_argument, NULL, 'r'},
1967 {"verbose", no_argument, NULL, 'v'},
1968 {"keycheck", no_argument, NULL, 'k'},
1969 {"find-package", no_argument, NULL, 'f'},
1970 {"list-package", no_argument, NULL, 'l'},
1971 {"package-query", no_argument, NULL, 'p'},
1972 {"help", no_argument, NULL, 'h'},
1973 {"version", no_argument, 0, 'V'},
1974 {0, no_argument, NULL, 0}
1977 static char opts[] = "cdsrvkflphV";
1982 const char *v = strchr (version, ':');
1992 len = strchr (v, ' ') - v;
1995 cygcheck version %.*s\n\
1996 System Checker for Cygwin\n\
1997 Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc.\n\
1999 ", len, v, __DATE__);
2005 int n = 1 + strchr (ev, '=') - ev;
2006 char *s = (char *) alloca (n + 1);
2013 unsigned long (*cygwin_internal) (int, ...);
2017 load_cygwin (int& argc, char **&argv)
2021 if (!(h = LoadLibrary ("cygwin1.dll")))
2023 if ((cygwin_internal = (DWORD (*) (int, ...)) GetProcAddress (h, "cygwin_internal")))
2025 char **av = (char **) cygwin_internal (CW_ARGV);
2026 if (av && ((DWORD) av != (DWORD) -1))
2028 /* Copy cygwin's idea of the argument list into this Window application. */
2029 for (argc = 0; av[argc]; argc++)
2031 argv = (char **) calloc (argc + 1, sizeof (char *));
2032 for (char **argvp = argv; *av; av++)
2033 *argvp++ = strdup (*av);
2037 char **envp = (char **) cygwin_internal (CW_ENVP);
2038 if (envp && ((DWORD) envp != (DWORD) -1))
2040 /* Store path and revert to this value, otherwise path gets overwritten
2041 by the POSIXy Cygwin variation, which breaks cygcheck.
2042 Another approach would be to use the Cygwin PATH and convert it to
2046 while (*(env = _environ))
2048 if (strncmp (*env, "PATH=", 5) == 0)
2049 path = strdup (*env);
2052 for (char **ev = envp; *ev; ev++)
2053 if (strncmp (*ev, "PATH=", 5) != 0)
2063 main (int argc, char **argv)
2067 load_cygwin (argc, argv);
2069 /* Need POSIX sorting while parsing args, but don't forget the
2070 user's original environment. */
2071 char *posixly = getenv ("POSIXLY_CORRECT");
2072 if (posixly == NULL)
2073 (void) putenv("POSIXLY_CORRECT=1");
2074 while ((i = getopt_long (argc, argv, opts, longopts, NULL)) != EOF)
2115 if (posixly == NULL)
2116 putenv ("POSIXLY_CORRECT=");
2118 if (argc == 0 && !sysinfo && !keycheck && !check_setup && !list_package)
2124 if ((check_setup || sysinfo || find_package || list_package || grep_packages)
2128 if ((find_package || list_package || grep_packages) && check_setup)
2131 if (dump_only && !check_setup)
2134 if (find_package + list_package + grep_packages > 1)
2138 return check_keys ();
2140 return package_grep (*argv);
2144 /* FIXME: Add help for check_setup and {list,find}_package */
2145 if (argc >= 1 && givehelp && !check_setup && !find_package && !list_package)
2147 printf("Here is where the OS will find your program%s, and which dlls\n",
2148 argc > 1 ? "s" : "");
2149 printf ("will be used for it. Use -v to see DLL version info\n");
2156 dump_setup (verbose, argv, !dump_only);
2157 else if (find_package)
2158 package_find (verbose, argv);
2159 else if (list_package)
2160 package_list (verbose, argv);
2162 for (i = 0; i < argc; i++)
2166 ok &= cygcheck (argv[i]);
2175 dump_setup (verbose, NULL, false);
2179 puts ("Use -h to see help about each section");
2182 return ok ? EXIT_SUCCESS : EXIT_FAILURE;