3 Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
4 2006, 2007, 2008, 2009 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
23 #include "wide_path.h"
25 #include "cygwin/include/sys/cygwin.h"
26 #include "cygwin/include/mntent.h"
27 #undef cygwin_internal
29 #define alloca __builtin_alloca
40 int grep_packages
= 0;
42 static char emptystr
[] = "";
44 /* This is global because it's used in both internet_display_error as well
46 BOOL (WINAPI
*pInternetCloseHandle
) (HINTERNET
);
49 typedef long long longlong
;
51 typedef __int64 longlong
;
54 /* In dump_setup.cc */
55 void dump_setup (int, char **, bool);
56 void package_find (int, char **);
57 void package_list (int, char **);
59 void dump_dodgy_apps (int verbose
);
62 static const char version
[] = "$Revision$";
64 static const char *known_env_vars
[] = {
72 "gcc_default_options",
94 static common_apps
[] = {
123 static int num_paths
, max_paths
;
128 void check_existence (const char *fn
, int showall
, int verbose
,
129 char* first
, const char *ext1
= "",
130 const char *ext2
= "");
134 int first_nonsys_path
;
137 eprintf (const char *format
, ...)
140 va_start (ap
, format
);
141 vfprintf (stderr
, format
, ap
);
146 * display_error() is used to report failure modes
149 display_error (const char *name
, bool show_error
, bool print_failed
)
151 fprintf (stderr
, "cygcheck: %s", name
);
153 fprintf (stderr
, "%s: %lu\n",
154 print_failed
? " failed" : "", GetLastError ());
156 fprintf (stderr
, "%s\n",
157 print_failed
? " failed" : "");
162 display_error (const char *name
)
164 return display_error (name
, true, true);
168 display_error (const char *fmt
, const char *x
)
171 snprintf (buf
, sizeof buf
, fmt
, x
);
172 return display_error (buf
, false, false);
176 display_error_fmt (const char *fmt
, ...)
182 vsnprintf (buf
, sizeof buf
, fmt
, va
);
183 return display_error (buf
, false, false);
186 /* Display a WinInet error message, and close a variable number of handles.
187 (Passed a list of handles terminated by NULL.) */
189 display_internet_error (const char *message
, ...)
191 DWORD err
= GetLastError ();
196 /* in the case of a successful connection but 404 response, there is no
197 win32 error message, but we still get passed a message to display. */
200 if (FormatMessage (FORMAT_MESSAGE_FROM_HMODULE
,
201 GetModuleHandle ("wininet.dll"), err
, 0, err_buf
,
202 sizeof (err_buf
), NULL
) == 0)
203 strcpy (err_buf
, "(Unknown error)");
205 fprintf (stderr
, "cygcheck: %s: %s (win32 error %lu)\n", message
,
209 fprintf (stderr
, "cygcheck: %s\n", message
);
211 va_start (hptr
, message
);
212 while ((h
= va_arg (hptr
, HINTERNET
)) != 0)
213 pInternetCloseHandle (h
);
220 add_path (char *s
, int maxlen
, bool issys
)
222 if (num_paths
>= max_paths
)
225 /* Extend path array */
226 paths
= (pathlike
*) realloc (paths
, (1 + max_paths
) * sizeof (paths
[0]));
229 pathlike
*pth
= paths
+ num_paths
;
231 /* Allocate space for directory in path list */
232 char *dir
= (char *) calloc (maxlen
+ 2, sizeof (char));
235 display_error ("add_path: calloc() failed");
239 /* Copy input directory to path list */
240 memcpy (dir
, s
, maxlen
);
242 /* Add a trailing slash by default */
243 char *e
= strchr (dir
, '\0');
244 if (e
!= dir
&& e
[-1] != '\\')
247 /* Fill out this element */
258 add_path ((char *) ".", 1, true); /* to be replaced later */
260 if (GetCurrentDirectory (4000, tmp
))
261 add_path (tmp
, strlen (tmp
), true);
263 display_error ("init_paths: GetCurrentDirectory()");
265 if (GetSystemDirectory (tmp
, 4000))
266 add_path (tmp
, strlen (tmp
), true);
268 display_error ("init_paths: GetSystemDirectory()");
269 sl
= strrchr (tmp
, '\\');
272 strcpy (sl
, "\\SYSTEM");
273 add_path (tmp
, strlen (tmp
), true);
275 GetWindowsDirectory (tmp
, 4000);
276 add_path (tmp
, strlen (tmp
), true);
278 char *wpath
= getenv ("PATH");
280 display_error ("WARNING: PATH is not set\n", "");
287 for (e
= b
; *e
&& *e
!= ';'; e
++)
288 continue; /* loop terminates at first ';' or EOS */
289 if (strncmp(b
, ".\\", 2) != 0)
290 add_path (b
, e
- b
, false);
298 #define LINK_EXTENSION ".lnk"
301 pathlike::check_existence (const char *fn
, int showall
, int verbose
,
302 char* first
, const char *ext1
, const char *ext2
)
310 wide_path
wpath (file
);
311 if (GetFileAttributesW (wpath
) != (DWORD
) - 1)
313 char *lastdot
= strrchr (file
, '.');
314 bool is_link
= lastdot
&& !strcmp (lastdot
, LINK_EXTENSION
);
315 // If file is a link, fix up the extension before printing
319 printf ("Found: %s\n", file
);
320 if (verbose
&& *first
!= '\0' && strcasecmp (first
, file
) != 0)
322 char *flastdot
= strrchr (first
, '.');
323 bool f_is_link
= flastdot
&& !strcmp (flastdot
, LINK_EXTENSION
);
324 // if first is a link, fix up the extension before printing
327 printf ("Warning: %s hides %s\n", first
, file
);
334 strcpy (first
, file
);
339 find_on_path (const char *in_file
, const char *ext
, bool showall
= false,
340 bool search_sys
= false, bool checklinks
= false)
342 static char rv
[4000];
344 /* Sort of a kludge but we've already tested this once, so don't try it again */
348 static pathlike abspath
[2] =
357 display_error ("internal error find_on_path: NULL pointer for file", false, false);
363 display_error ("internal error find_on_path: NULL pointer for default_extension", false, false);
368 pathlike
*search_paths
;
369 if (!strpbrk (in_file
, ":/\\"))
372 search_paths
= paths
;
376 file
= cygpath (in_file
, NULL
);
377 search_paths
= abspath
;
383 display_error ("internal error find_on_path: cygpath conversion failed for %s\n", in_file
);
387 char *hasext
= strrchr (file
, '.');
388 if (hasext
&& !strpbrk (hasext
, "/\\"))
391 for (pathlike
*pth
= search_paths
; pth
->dir
; pth
++)
392 if (!pth
->issys
|| search_sys
)
394 pth
->check_existence (file
, showall
, verbose
, rv
, ext
);
397 pth
->check_existence (file
, showall
, verbose
, rv
, ext
, LINK_EXTENSION
);
402 pth
->check_existence (file
, showall
, verbose
, rv
);
404 pth
->check_existence (file
, showall
, verbose
, rv
, LINK_EXTENSION
);
407 return *rv
? rv
: NULL
;
412 #define DID_INACTIVE 3
423 already_did (const char *file
)
426 for (d
= did
; d
; d
= d
->next
)
427 if (strcasecmp (d
->file
, file
) == 0)
429 d
= (Did
*) malloc (sizeof (Did
));
430 d
->file
= strdup (file
);
442 int size_of_raw_data
;
443 int pointer_to_raw_data
;
447 rva_to_offset (int rva
, char *sections
, int nsections
, int *sz
)
451 if (sections
== NULL
)
453 display_error ("rva_to_offset: NULL passed for sections", true, false);
457 for (i
= 0; i
< nsections
; i
++)
459 Section
*s
= (Section
*) (sections
+ i
* 40);
461 printf ("%08x < %08x < %08x ? %08x\n",
462 s
->virtual_address
, rva
,
463 s
->virtual_address
+ s
->virtual_size
, s
->pointer_to_raw_data
);
465 if (rva
>= s
->virtual_address
466 && rva
< s
->virtual_address
+ s
->virtual_size
)
469 *sz
= s
->virtual_address
+ s
->virtual_size
- rva
;
470 return rva
- s
->virtual_address
+ s
->pointer_to_raw_data
;
487 unsigned characteristics
;
489 unsigned forwarder_chain
;
494 static bool track_down (const char *file
, const char *suffix
, int lvl
);
496 #define CYGPREFIX (sizeof ("%%% Cygwin ") - 1)
498 cygwin_info (HANDLE h
)
500 char *buf
, *bufend
, *buf_start
= NULL
;
501 const char *hello
= " Cygwin DLL version info:\n";
502 DWORD size
= GetFileSize (h
, NULL
);
505 if (size
== 0xffffffff)
508 buf_start
= buf
= (char *) calloc (1, size
+ 1);
511 display_error ("cygwin_info: calloc()");
515 (void) SetFilePointer (h
, 0, NULL
, FILE_BEGIN
);
516 if (!ReadFile (h
, buf
, size
, &n
, NULL
))
522 static char dummy
[] = "\0\0\0\0\0\0\0";
523 char *dll_major
= dummy
;
526 if ((buf
= (char *) memchr (buf
, '%', bufend
- buf
)) == NULL
)
528 else if (strncmp ("%%% Cygwin ", buf
, CYGPREFIX
) != 0)
532 char *p
= strchr (buf
+= CYGPREFIX
, '\n');
535 if (strncasecmp (buf
, "dll major:", 10) == 0)
537 dll_major
= buf
+ 11;
543 if (strncasecmp (buf
, "dll minor:", 10) != 0)
547 char c
= dll_major
[1];
549 int maj
= atoi (dll_major
);
551 int min
= atoi (dll_major
+ 1);
552 sprintf (pbuf
, "DLL version: %d.%d.%.*s", maj
, min
, len
- 11,
554 len
= strlen (s
= pbuf
);
556 if (strncmp (s
, "dll", 3) == 0)
557 memcpy (s
, "DLL", 3);
558 else if (strncmp (s
, "api", 3) == 0)
559 memcpy (s
, "API", 3);
560 else if (islower (*s
))
562 fprintf (stdout
, "%s %.*s", hello
, len
, s
);
574 dll_info (const char *path
, HANDLE fh
, int lvl
, int recurse
)
578 int pe_header_offset
= get_dword (fh
, 0x3c);
579 if (GetLastError () != NO_ERROR
)
580 display_error ("get_dword");
581 int opthdr_ofs
= pe_header_offset
+ 4 + 20;
586 display_error ("dll_info: NULL passed for path", true, false);
590 if (SetFilePointer (fh
, opthdr_ofs
+ 40, 0, FILE_BEGIN
) ==
591 INVALID_SET_FILE_POINTER
&& GetLastError () != NO_ERROR
)
592 display_error ("dll_info: SetFilePointer()");
594 if (!ReadFile (fh
, &v
, sizeof (v
), &junk
, 0))
595 display_error ("dll_info: Readfile()");
598 printf (" - os=%d.%d img=%d.%d sys=%d.%d\n",
599 v
[0], v
[1], v
[2], v
[3], v
[4], v
[5]);
603 int num_entries
= get_dword (fh
, opthdr_ofs
+ 92);
604 if (GetLastError () != NO_ERROR
)
605 display_error ("get_dword");
606 int export_rva
= get_dword (fh
, opthdr_ofs
+ 96);
607 if (GetLastError () != NO_ERROR
)
608 display_error ("get_dword");
609 int export_size
= get_dword (fh
, opthdr_ofs
+ 100);
610 if (GetLastError () != NO_ERROR
)
611 display_error ("get_dword");
612 int import_rva
= get_dword (fh
, opthdr_ofs
+ 104);
613 if (GetLastError () != NO_ERROR
)
614 display_error ("get_dword");
615 int import_size
= get_dword (fh
, opthdr_ofs
+ 108);
616 if (GetLastError () != NO_ERROR
)
617 display_error ("get_dword");
619 int nsections
= get_word (fh
, pe_header_offset
+ 4 + 2);
621 display_error ("get_word");
622 char *sections
= (char *) malloc (nsections
* 40);
624 if (SetFilePointer (fh
, pe_header_offset
+ 4 + 20 +
625 get_word (fh
, pe_header_offset
+ 4 + 16), 0,
626 FILE_BEGIN
) == INVALID_SET_FILE_POINTER
627 && GetLastError () != NO_ERROR
)
628 display_error ("dll_info: SetFilePointer()");
630 if (!ReadFile (fh
, sections
, nsections
* 40, &junk
, 0))
631 display_error ("dll_info: Readfile()");
633 if (verbose
&& num_entries
>= 1 && export_size
> 0)
636 int expbase
= rva_to_offset (export_rva
, sections
, nsections
, &expsz
);
640 if (SetFilePointer (fh
, expbase
, 0, FILE_BEGIN
) ==
641 INVALID_SET_FILE_POINTER
&& GetLastError () != NO_ERROR
)
642 display_error ("dll_info: SetFilePointer()");
644 unsigned char *exp
= (unsigned char *) malloc (expsz
);
646 if (!ReadFile (fh
, exp
, expsz
, &junk
, 0))
647 display_error ("dll_info: Readfile()");
649 ExpDirectory
*ed
= (ExpDirectory
*) exp
;
650 int ofs
= ed
->name_rva
- export_rva
;
651 struct tm
*tm
= localtime ((const time_t *) &(ed
->timestamp
));
652 if (tm
->tm_year
< 60)
654 if (tm
->tm_year
< 200)
656 printf ("%*c", lvl
+ 2, ' ');
657 printf ("\"%s\" v%d.%d ts=", exp
+ ofs
,
658 ed
->major_ver
, ed
->minor_ver
);
659 printf ("%d/%d/%d %d:%02d\n",
660 tm
->tm_year
, tm
->tm_mon
+ 1, tm
->tm_mday
,
661 tm
->tm_hour
, tm
->tm_min
);
665 if (num_entries
>= 2 && import_size
> 0 && recurse
)
668 int impbase
= rva_to_offset (import_rva
, sections
, nsections
, &impsz
);
671 if (SetFilePointer (fh
, impbase
, 0, FILE_BEGIN
) ==
672 INVALID_SET_FILE_POINTER
&& GetLastError () != NO_ERROR
)
673 display_error ("dll_info: SetFilePointer()");
675 unsigned char *imp
= (unsigned char *) malloc (impsz
);
678 display_error ("dll_info: malloc()");
682 if (!ReadFile (fh
, imp
, impsz
, &junk
, 0))
683 display_error ("dll_info: Readfile()");
685 ImpDirectory
*id
= (ImpDirectory
*) imp
;
686 for (i
= 0; id
[i
].name_rva
; i
++)
688 /* int ofs = id[i].name_rva - import_rva; */
689 track_down ((char *) imp
+ id
[i
].name_rva
- import_rva
,
690 (char *) ".dll", lvl
+ 2);
694 if (strstr (path
, "\\cygwin1.dll"))
698 // Return true on success, false if error printed
700 track_down (const char *file
, const char *suffix
, int lvl
)
704 display_error ("track_down: NULL passed for file", true, false);
710 display_error ("track_down: NULL passed for suffix", false, false);
714 const char *path
= find_on_path (file
, suffix
, false, true);
717 display_error ("track_down: could not find %s\n", file
);
721 Did
*d
= already_did (file
);
730 printf ("%*c", lvl
, ' ');
732 printf (" (recursive)\n");
739 printf ("%*c", lvl
, ' ');
741 printf (" (already done)\n");
749 printf ("%*c", lvl
, ' ');
753 display_error ("file not found - '%s'\n", file
);
759 wide_path
wpath (path
);
761 CreateFileW (wpath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
762 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
763 if (fh
== INVALID_HANDLE_VALUE
)
765 display_error ("cannot open - '%s'\n", path
);
769 d
->state
= DID_ACTIVE
;
772 dll_info (path
, fh
, lvl
, 1);
773 else if (is_symlink (fh
))
774 display_error ("%s is a symlink instead of a DLL\n", path
);
777 int magic
= get_word (fh
, 0x0);
779 display_error ("get_word");
781 display_error_fmt ("%s is not a DLL: magic number %x (%d) '%s'\n",
782 path
, magic
, magic
, (char *)&magic
);
785 d
->state
= DID_INACTIVE
;
786 if (!CloseHandle (fh
))
787 display_error ("track_down: CloseHandle()");
795 HANDLE h
= CreateFileW (wpath
, GENERIC_READ
,
796 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
797 0, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0);
798 BY_HANDLE_FILE_INFORMATION info
;
800 if (!GetFileInformationByHandle (h
, &info
))
801 display_error ("ls: GetFileInformationByHandle()");
805 if (!FileTimeToSystemTime (&info
.ftLastWriteTime
, &systime
))
806 display_error ("ls: FileTimeToSystemTime()");
807 printf ("%5dk %04d/%02d/%02d %s",
808 (((int) info
.nFileSizeLow
) + 512) / 1024,
809 systime
.wYear
, systime
.wMonth
, systime
.wDay
, f
);
810 dll_info (f
, h
, 16, 0);
811 if (!CloseHandle (h
))
812 display_error ("ls: CloseHandle()");
815 /* Remove filename from 's' and return directory name without trailing
816 backslash, or NULL if 's' doesn't seem to have a dirname. */
818 dirname (const char *s
)
820 static char buf
[PATH_MAX
];
825 strncpy (buf
, s
, PATH_MAX
);
826 buf
[PATH_MAX
- 1] = '\0'; // in case strlen(s) > PATH_MAX
827 char *lastsep
= strrchr (buf
, '\\');
829 return NULL
; // no backslash -> no dirname
830 else if (lastsep
- buf
<= 2 && buf
[1] == ':')
831 lastsep
[1] = '\0'; // can't remove backslash of "x:\"
837 // Find a real application on the path (possibly following symlinks)
839 find_app_on_path (const char *app
, bool showall
= false)
841 const char *papp
= find_on_path (app
, ".exe", showall
, false, true);
846 wide_path
wpath (papp
);
848 CreateFileW (wpath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
849 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
850 if (fh
== INVALID_HANDLE_VALUE
)
855 static char tmp
[SYMLINK_MAX
+ 1];
856 if (!readlink (fh
, tmp
, SYMLINK_MAX
))
857 display_error("readlink failed");
859 /* Resolve the linkname relative to the directory of the link. */
860 char *ptr
= cygpath_rel (dirname (papp
), tmp
, NULL
);
861 printf (" -> %s\n", ptr
);
862 if (!strchr (ptr
, '\\'))
865 strncpy (tmp
, cygpath (papp
, NULL
), SYMLINK_MAX
);
866 lastsep
= strrchr (tmp
, '\\');
867 strncpy (lastsep
+1, ptr
, SYMLINK_MAX
- (lastsep
-tmp
));
870 if (!CloseHandle (fh
))
871 display_error ("find_app_on_path: CloseHandle()");
872 /* FIXME: We leak the ptr returned by cygpath() here which is a
874 return find_app_on_path (ptr
, showall
);
877 if (!CloseHandle (fh
))
878 display_error ("find_app_on_path: CloseHandle()");
882 // Return true on success, false if error printed
884 cygcheck (const char *app
)
886 const char *papp
= find_app_on_path (app
, 1);
889 display_error ("could not find '%s'\n", app
);
894 char *sep
= strpbrk (papp
, ":/\\");
897 static char dot
[] = ".";
903 s
= (char *) malloc (n
+ 2);
904 memcpy ((char *) s
, papp
, n
);
905 strcpy (s
+ n
, "\\");
910 return track_down (papp
, ".exe", 0);
921 show_reg (RegInfo
* ri
, int nest
)
925 show_reg (ri
->prev
, 1);
927 printf ("%s\\", ri
->name
);
929 printf ("%s\n", ri
->name
);
933 scan_registry (RegInfo
* prev
, HKEY hKey
, char *name
, int cygwin
, bool wow64
)
941 for (cp
= name
; *cp
; cp
++)
942 if (strncasecmp (cp
, "Cygwin", 6) == 0)
945 DWORD num_subkeys
, max_subkey_len
, num_values
;
946 DWORD max_value_len
, max_valdata_len
, i
;
947 if (RegQueryInfoKey (hKey
, 0, 0, 0, &num_subkeys
, &max_subkey_len
, 0,
948 &num_values
, &max_value_len
, &max_valdata_len
, 0, 0)
953 FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
, 0, GetLastError (),
954 MAKELANGID (LANG_NEUTRAL
, SUBLANG_DEFAULT
), tmp
, 400, 0);
955 printf ("RegQueryInfoKey: %s\n", tmp
);
964 char *value_name
= (char *) malloc (max_value_len
+ 1);
965 if (value_name
== NULL
)
967 display_error ("scan_registry: malloc()");
971 char *value_data
= (char *) malloc (max_valdata_len
+ 1);
972 if (value_data
== NULL
)
974 display_error ("scan_registry: malloc()");
978 for (i
= 0; i
< num_values
; i
++)
980 DWORD dlen
= max_valdata_len
+ 1;
981 DWORD nlen
= max_value_len
+ 1;
983 RegEnumValue (hKey
, i
, value_name
, &nlen
, 0,
984 &type
, (BYTE
*) value_data
, &dlen
);
986 printf (" %s = ", i
? value_name
: "(default)");
990 printf ("0x%08x\n", *(unsigned *) value_data
);
994 printf ("'%s'\n", value_data
);
997 printf ("(unsupported type)\n");
1006 char *subkey_name
= (char *) malloc (max_subkey_len
+ 1);
1007 for (i
= 0; i
< num_subkeys
; i
++)
1009 if (RegEnumKey (hKey
, i
, subkey_name
, max_subkey_len
+ 1) ==
1013 /* Don't recurse more than one level into the WOW64 subkey since
1014 that would lead to an endless recursion. */
1015 if (!strcasecmp (subkey_name
, "Wow6432Node"))
1021 if (RegOpenKeyEx (hKey
, subkey_name
, 0, KEY_READ
, &sKey
)
1024 scan_registry (&ri
, sKey
, subkey_name
, cygwin
, wow64
);
1025 if (RegCloseKey (sKey
) != ERROR_SUCCESS
)
1026 display_error ("scan_registry: RegCloseKey()");
1034 pretty_id (const char *s
, char *cygwin
, size_t cyglen
)
1036 char *groups
[16384];
1038 strcpy (cygwin
+ cyglen
++, " ");
1039 strcpy (cygwin
+ cyglen
, s
);
1042 char *id
= cygpath ("/bin/id.exe", NULL
);
1043 for (char *p
= id
; (p
= strchr (p
, '/')); p
++)
1046 if (access (id
, X_OK
))
1048 fprintf (stderr
, "'id' program not found\n");
1053 snprintf (buf
, sizeof (buf
), "\"%s\"", id
);
1054 FILE *f
= popen (buf
, "rt");
1057 fgets (buf
, sizeof (buf
), f
);
1059 char *uid
= strtok (buf
, ")");
1061 uid
+= strlen ("uid=");
1064 fprintf (stderr
, "garbled output from 'id' command - no uid= found\n");
1067 char *gid
= strtok (NULL
, ")");
1069 gid
+= strlen ("gid=") + 1;
1072 fprintf (stderr
, "garbled output from 'id' command - no gid= found\n");
1076 char **ng
= groups
- 1;
1077 size_t len_uid
= strlen ("UID: )") + strlen (uid
);
1078 size_t len_gid
= strlen ("GID: )") + strlen (gid
);
1079 *++ng
= groups
[0] = (char *) alloca (len_uid
+ 1);
1080 *++ng
= groups
[1] = (char *) alloca (len_gid
+ 1);
1081 sprintf (groups
[0], "UID: %s)", uid
);
1082 sprintf (groups
[1], "GID: %s)", gid
);
1083 size_t sz
= max (len_uid
, len_gid
);
1084 while ((*++ng
= strtok (NULL
, ",")))
1086 char *p
= strchr (*ng
, '\n');
1089 if (ng
== groups
+ 2)
1090 *ng
+= strlen (" groups=");
1091 size_t len
= strlen (*ng
);
1097 printf ("\nOutput from %s (%s)\n", id
, s
);
1098 int n
= 80 / (int) ++sz
;
1099 int i
= n
> 2 ? n
- 2 : 0;
1101 for (char **g
= groups
; g
<= ng
; g
++)
1102 if ((g
!= ng
) && (++i
< n
))
1103 printf ("%*s", sz
, *g
);
1111 /* This dumps information about each installed cygwin service, if cygrunsrv
1114 dump_sysinfo_services ()
1119 bool no_services
= false;
1122 printf ("\nChecking for any Cygwin services... %s\n\n",
1123 verbose
? "" : "(use -v for more detail)");
1125 fputc ('\n', stdout
);
1127 /* find the location of cygrunsrv.exe */
1128 char *cygrunsrv
= cygpath ("/bin/cygrunsrv.exe", NULL
);
1129 for (char *p
= cygrunsrv
; (p
= strchr (p
, '/')); p
++)
1132 if (access (cygrunsrv
, X_OK
))
1134 puts ("Can't find the cygrunsrv utility, skipping services check.\n");
1138 /* check for a recent cygrunsrv */
1139 snprintf (buf
, sizeof (buf
), "\"%s\" --version", cygrunsrv
);
1140 if ((f
= popen (buf
, "rt")) == NULL
)
1142 printf ("Failed to execute '%s', skipping services check.\n", buf
);
1146 int ret
= fscanf (f
, "cygrunsrv V%u.%u", &maj
, &min
);
1147 if (ferror (f
) || feof (f
) || ret
== EOF
|| maj
< 1 || min
< 10)
1149 puts ("The version of cygrunsrv installed is too old to dump service info.\n");
1154 /* For verbose mode, just run cygrunsrv --list --verbose and copy output
1155 verbatim; otherwise run cygrunsrv --list and then cygrunsrv --query for
1157 snprintf (buf
, sizeof (buf
), (verbose
? "\"%s\" --list --verbose" : "\"%s\" --list"),
1159 if ((f
= popen (buf
, "rt")) == NULL
)
1161 printf ("Failed to execute '%s', skipping services check.\n", buf
);
1167 /* copy output to stdout */
1169 while (!feof (f
) && !ferror (f
))
1170 nchars
+= fwrite ((void *) buf
, 1,
1171 fread ((void *) buf
, 1, sizeof (buf
), f
), stdout
);
1173 /* cygrunsrv outputs nothing if there are no cygwin services found */
1180 /* read the output of --list, and then run --query for each service */
1181 size_t nchars
= fread ((void *) buf
, 1, sizeof (buf
) - 1, f
);
1186 for (char *srv
= strtok (buf
, "\n"); srv
; srv
= strtok (NULL
, "\n"))
1188 snprintf (buf2
, sizeof (buf2
), "\"%s\" --query %s", cygrunsrv
, srv
);
1189 if ((f
= popen (buf2
, "rt")) == NULL
)
1191 printf ("Failed to execute '%s', skipping services check.\n", buf2
);
1195 /* copy output to stdout */
1196 while (!feof (f
) && !ferror (f
))
1197 fwrite ((void *) buf2
, 1,
1198 fread ((void *) buf2
, 1, sizeof (buf2
), f
), stdout
);
1205 /* inform the user if nothing found */
1207 puts ("No Cygwin services found.\n");
1216 char *found_cygwin_dll
;
1218 bool more_info
= true;
1220 DWORD obcaseinsensitive
= 1;
1223 printf ("\nCygwin Configuration Diagnostics\n");
1225 printf ("Current System Time: %s\n", ctime (&now
));
1227 OSVERSIONINFOEX osversion
;
1228 osversion
.dwOSVersionInfoSize
= sizeof (OSVERSIONINFOEX
);
1229 if (!GetVersionEx (reinterpret_cast<LPOSVERSIONINFO
>(&osversion
)))
1232 osversion
.dwOSVersionInfoSize
= sizeof (OSVERSIONINFO
);
1233 if (!GetVersionEx (reinterpret_cast<LPOSVERSIONINFO
>(&osversion
)))
1234 display_error ("dump_sysinfo: GetVersionEx()");
1237 HMODULE k32
= LoadLibrary ("kernel32.dll");
1239 switch (osversion
.dwPlatformId
)
1241 case VER_PLATFORM_WIN32s
:
1242 strcpy (osname
, "32s (not supported)");
1244 case VER_PLATFORM_WIN32_WINDOWS
:
1245 strcpy (osname
, "95/98/Me (not supported)");
1247 case VER_PLATFORM_WIN32_NT
:
1249 if (osversion
.dwMajorVersion
== 6)
1251 BOOL (WINAPI
*GetProductInfo
) (DWORD
, DWORD
, DWORD
, DWORD
, PDWORD
) =
1252 (BOOL (WINAPI
*)(DWORD
, DWORD
, DWORD
, DWORD
, PDWORD
))
1253 GetProcAddress (k32
, "GetProductInfo");
1254 if (osversion
.dwMinorVersion
== 0)
1255 strcpy (osname
, osversion
.wProductType
== VER_NT_WORKSTATION
1256 ? "Vista" : "2008");
1257 else if (osversion
.dwMinorVersion
== 1)
1258 strcpy (osname
, osversion
.wProductType
== VER_NT_WORKSTATION
1261 if (GetProductInfo (osversion
.dwMajorVersion
,
1262 osversion
.dwMinorVersion
,
1263 osversion
.wServicePackMajor
,
1264 osversion
.wServicePackMinor
,
1267 #define PRODUCT_UNLICENSED 0xabcdabcd
1268 #define PRODUCT_HYPERV 0x2a
1269 const char *products
[] =
1279 " Server Datacenter",
1280 " Small Business Server",
1281 " Server Enterprise",
1283 " Server Datacenter Core",
1284 " Server Standard Core",
1285 " Server Enterprise Core",
1286 " Server Enterprise for Itanium-based Systems",
1291 " Storage Server Express",
1292 " Storage Server Standard",
1293 " Storage Server Workgroup",
1294 " Storage Server Enterprise",
1295 " for Windows Essential Server Solutions",
1296 " Small Business Server Premium",
1301 " Essential Business Server Management Server",
1302 " Essential Business Server Security Server"
1303 " Essential Business Server Messaging Server",
1304 " Server Foundation",
1306 " without Hyper-V for Windows Essential Server Solutions",
1307 " Server Standard without Hyper-V",
1308 " Server Datacenter without Hyper-V",
1309 " Server Enterprise without Hyper-V",
1310 " Server Datacenter Core without Hyper-V",
1311 " Server Standard Core without Hyper-V",
1312 " Server Enterprise Core without Hyper-V",
1315 if (prod
== PRODUCT_UNLICENSED
)
1316 strcat (osname
, "Unlicensed");
1317 else if (prod
> PRODUCT_HYPERV
)
1318 strcat (osname
, "");
1320 strcat (osname
, products
[prod
]);
1326 else if (osversion
.dwMajorVersion
== 5)
1328 if (osversion
.dwMinorVersion
== 0)
1330 strcpy (osname
, "2000");
1331 if (osversion
.wProductType
== VER_NT_WORKSTATION
)
1332 strcat (osname
, " Professional");
1333 else if (osversion
.wSuiteMask
& VER_SUITE_DATACENTER
)
1334 strcat (osname
, " Datacenter Server");
1335 else if (osversion
.wSuiteMask
& VER_SUITE_ENTERPRISE
)
1336 strcat (osname
, " Advanced Server");
1338 strcat (osname
, " Server");
1340 else if (osversion
.dwMinorVersion
== 1)
1342 strcpy (osname
, "XP");
1343 if (GetSystemMetrics (SM_MEDIACENTER
))
1344 strcat (osname
, " Media Center Edition");
1345 else if (GetSystemMetrics (SM_TABLETPC
))
1346 strcat (osname
, " Tablet PC Edition");
1347 else if (GetSystemMetrics (SM_STARTER
))
1348 strcat (osname
, " Starter Edition");
1349 else if (osversion
.wSuiteMask
& VER_SUITE_PERSONAL
)
1350 strcat (osname
, " Home Edition");
1352 strcat (osname
, " Professional");
1354 else if (osversion
.dwMinorVersion
== 2)
1356 strcpy (osname
, "2003 Server");
1357 if (GetSystemMetrics (SM_SERVERR2
))
1358 strcat (osname
, " R2");
1359 if (osversion
.wSuiteMask
& VER_SUITE_BLADE
)
1360 strcat (osname
, " Web Edition");
1361 else if (osversion
.wSuiteMask
& VER_SUITE_DATACENTER
)
1362 strcat (osname
, " Datacenter Edition");
1363 else if (osversion
.wSuiteMask
& VER_SUITE_ENTERPRISE
)
1364 strcat (osname
, " Enterprise Edition");
1365 else if (osversion
.wSuiteMask
& VER_SUITE_COMPUTE_SERVER
)
1366 strcat (osname
, " Compute Cluster Edition");
1369 else if (osversion
.dwMajorVersion
== 4)
1371 strcpy (osname
, "NT 4");
1374 if (osversion
.wProductType
== VER_NT_WORKSTATION
)
1375 strcat (osname
, " Workstation");
1378 strcat (osname
, " Server");
1379 if (osversion
.wSuiteMask
& VER_SUITE_ENTERPRISE
)
1380 strcat (osname
, " Enterprise Edition");
1385 strcpy (osname
, "NT");
1388 strcpy (osname
, "??");
1391 printf ("Windows %s Ver %lu.%lu Build %lu %s\n", osname
,
1392 osversion
.dwMajorVersion
, osversion
.dwMinorVersion
,
1393 osversion
.dwPlatformId
== VER_PLATFORM_WIN32_NT
?
1394 osversion
.dwBuildNumber
: (osversion
.dwBuildNumber
& 0xffff),
1395 osversion
.dwPlatformId
== VER_PLATFORM_WIN32_NT
?
1396 osversion
.szCSDVersion
: "");
1398 if (osversion
.dwPlatformId
== VER_PLATFORM_WIN32s
1399 || osversion
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
)
1400 exit (EXIT_FAILURE
);
1402 BOOL (WINAPI
*wow64_func
) (HANDLE
, PBOOL
) = (BOOL (WINAPI
*) (HANDLE
, PBOOL
))
1403 GetProcAddress (k32
, "IsWow64Process");
1404 BOOL is_wow64
= FALSE
;
1405 if (wow64_func
&& wow64_func (GetCurrentProcess (), &is_wow64
) && is_wow64
)
1407 void (WINAPI
*nativinfo
) (LPSYSTEM_INFO
) = (void (WINAPI
*)
1408 (LPSYSTEM_INFO
)) GetProcAddress (k32
, "GetNativeSystemInfo");
1409 SYSTEM_INFO natinfo
;
1410 nativinfo (&natinfo
);
1411 fputs ("\nRunning under WOW64 on ", stdout
);
1412 switch (natinfo
.wProcessorArchitecture
)
1414 case PROCESSOR_ARCHITECTURE_IA64
:
1417 case PROCESSOR_ARCHITECTURE_AMD64
:
1426 if (GetSystemMetrics (SM_REMOTESESSION
))
1427 printf ("\nRunning in Terminal Service session\n");
1430 char *s
= getenv ("PATH"), *e
;
1435 char sep
= strchr (s
, ';') ? ';' : ':';
1436 int count_path_items
= 0;
1439 for (e
= s
; *e
&& *e
!= sep
; e
++);
1441 printf ("\t%.*s\n", e
- s
, s
);
1453 char *cygwin
= getenv ("CYGWIN");
1455 cygwin
-= strlen ("CYGWIN=");
1457 cygwin
= const_cast <char *> ("CYGWIN=");
1458 size_t cyglen
= strlen (cygwin
);
1459 cygwin
= strcpy ((char *) malloc (cyglen
+ sizeof (" nontsec")), cygwin
);
1460 pretty_id ("nontsec", cygwin
, cyglen
);
1461 pretty_id ("ntsec", cygwin
, cyglen
);
1465 if (!GetSystemDirectory (tmp
, 4000))
1466 display_error ("dump_sysinfo: GetSystemDirectory()");
1467 printf ("\nSysDir: %s\n", tmp
);
1469 GetWindowsDirectory (tmp
, 4000);
1470 printf ("WinDir: %s\n\n", tmp
);
1474 printf ("Here's some environment variables that may affect cygwin:\n");
1475 for (i
= 0; environ
[i
]; i
++)
1477 char *eq
= strchr (environ
[i
], '=');
1480 /* int len = eq - environ[i]; */
1481 for (j
= 0; known_env_vars
[j
]; j
++)
1484 if (strcmp (environ
[i
], "PATH") == 0)
1485 continue; /* we handle this one specially */
1486 if (strcasecmp (environ
[i
], known_env_vars
[j
]) == 0)
1487 printf ("%s = '%s'\n", environ
[i
], eq
+ 1);
1496 printf ("Here's the rest of your environment variables:\n");
1497 for (i
= 0; environ
[i
]; i
++)
1500 char *eq
= strchr (environ
[i
], '=');
1503 /* int len = eq - environ[i]; */
1504 for (j
= 0; known_env_vars
[j
]; j
++)
1507 if (strcasecmp (environ
[i
], known_env_vars
[j
]) == 0)
1514 printf ("%s = '%s'\n", environ
[i
], eq
+ 1);
1524 printf ("Scanning registry for keys with 'Cygwin' in them...\n");
1525 scan_registry (0, HKEY_CURRENT_USER
,
1526 (char *) "HKEY_CURRENT_USER", 0, false);
1527 scan_registry (0, HKEY_LOCAL_MACHINE
,
1528 (char *) "HKEY_LOCAL_MACHINE", 0, false);
1532 printf ("Use '-r' to scan registry\n\n");
1534 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE
,
1535 "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\kernel",
1536 0, KEY_READ
, &key
) == ERROR_SUCCESS
)
1539 RegQueryValueEx (key
, "obcaseinsensitive", NULL
, NULL
,
1540 (LPBYTE
) &obcaseinsensitive
, &size
);
1543 printf ("obcaseinsensitive set to %lu\n\n", obcaseinsensitive
);
1547 printf ("Listing available drives...\n");
1548 printf ("Drv Type Size Used Flags Name\n");
1551 SetErrorMode (SEM_FAILCRITICALERRORS
| SEM_NOOPENFILEERRORBOX
);
1552 int drivemask
= GetLogicalDrives ();
1554 BOOL (WINAPI
* gdfse
) (LPCSTR
, long long *, long long *, long long *) =
1555 (BOOL (WINAPI
*) (LPCSTR
, long long *, long long *, long long *))
1556 GetProcAddress (k32
, "GetDiskFreeSpaceExA");
1558 for (i
= 0; i
< 26; i
++)
1560 if (!(drivemask
& (1 << i
)))
1562 char drive
[4], name
[200], fsname
[200];
1563 DWORD serno
= 0, maxnamelen
= 0, flags
= 0;
1564 name
[0] = name
[0] = fsname
[0] = 0;
1565 sprintf (drive
, "%c:\\", i
+ 'a');
1566 /* Report all errors, except if the Volume is ERROR_NOT_READY.
1567 ERROR_NOT_READY is returned when removeable media drives are empty
1568 (CD, floppy, etc.) */
1569 if (!GetVolumeInformation (drive
, name
, sizeof (name
), &serno
,
1570 &maxnamelen
, &flags
, fsname
,
1572 && GetLastError () != ERROR_NOT_READY
)
1574 # define FMT "dump_sysinfo: GetVolumeInformation() for drive %c:"
1575 char buf
[sizeof (FMT
)];
1576 sprintf (buf
, FMT
, 'A' + i
);
1577 display_error (buf
);
1581 int dtype
= GetDriveType (drive
);
1582 char drive_type
[4] = "unk";
1585 case DRIVE_REMOVABLE
:
1586 strcpy (drive_type
, "fd ");
1589 strcpy (drive_type
, "hd ");
1592 strcpy (drive_type
, "net");
1595 strcpy (drive_type
, "cd ");
1598 strcpy (drive_type
, "ram");
1601 strcpy (drive_type
, "unk");
1604 long capacity_mb
= -1;
1605 int percent_full
= -1;
1607 long long free_me
= 0ULL, free_bytes
= 0ULL, total_bytes
= 1ULL;
1608 if (gdfse
!= NULL
&& gdfse (drive
, &free_me
, &total_bytes
, &free_bytes
))
1610 capacity_mb
= total_bytes
/ (1024L * 1024L);
1611 percent_full
= 100 - (int) ((100.0 * free_me
) / total_bytes
);
1615 DWORD spc
= 0, bps
= 0, fc
= 0, tc
= 1;
1616 if (GetDiskFreeSpace (drive
, &spc
, &bps
, &fc
, &tc
))
1618 capacity_mb
= (spc
* bps
* tc
) / (1024 * 1024);
1619 percent_full
= 100 - (int) ((100.0 * fc
) / tc
);
1623 printf ("%.2s %s %-6s ", drive
, drive_type
, fsname
);
1624 if (capacity_mb
>= 0)
1625 printf ("%7dMb %3d%% ", (int) capacity_mb
, (int) percent_full
);
1627 printf (" N/A N/A ");
1628 printf ("%s %s %s %s %s %s %s\n",
1629 flags
& FS_CASE_IS_PRESERVED
? "CP" : " ",
1630 flags
& FS_CASE_SENSITIVE
? "CS" : " ",
1631 flags
& FS_UNICODE_STORED_ON_DISK
? "UN" : " ",
1632 flags
& FS_PERSISTENT_ACLS
? "PA" : " ",
1633 flags
& FS_FILE_COMPRESSION
? "FC" : " ",
1634 flags
& FS_VOL_IS_COMPRESSED
? "VC" : " ",
1636 flags
& FILE_SUPPORTS_ENCRYPTION
? "EN" : " ",
1637 flags
& FILE_SUPPORTS_OBJECT_IDS
? "OI" : " ",
1638 flags
& FILE_SUPPORTS_REPARSE_POINTS
? "RP" : " ",
1639 flags
& FILE_SUPPORTS_SPARSE_FILES
? "SP" : " ",
1640 flags
& FILE_VOLUME_QUOTAS
? "QU" : " ",
1645 if (!FreeLibrary (k32
))
1646 display_error ("dump_sysinfo: FreeLibrary()");
1647 SetErrorMode (prev_mode
);
1651 "fd = floppy, hd = hard drive, cd = CD-ROM\n"
1652 "net= Network Share, ram= RAM drive, unk= Unknown\n"
1653 "CP = Case Preserving, CS = Case Sensitive, UN = Unicode\n"
1654 "PA = Persistent ACLS, FC = File Compression, VC = Volume Compression");
1658 unsigned ml_fsname
= 4, ml_dir
= 7, ml_type
= 6;
1659 bool ml_trailing
= false;
1663 while ((mnt
= getmntent (0)))
1665 unsigned n
= (int) strlen (mnt
->mnt_fsname
);
1666 ml_trailing
|= (n
> 1 && strchr ("\\/", mnt
->mnt_fsname
[n
- 1]));
1669 n
= (int) strlen (mnt
->mnt_dir
);
1670 ml_trailing
|= (n
> 1 && strchr ("\\/", mnt
->mnt_dir
[n
- 1]));
1676 puts ("Warning: Mount entries should not have a trailing (back)slash\n");
1681 ("Mount entries: these map POSIX directories to your NT drives.\n");
1682 printf ("%-*s %-*s %-*s %s\n", ml_fsname
, "-NT-", ml_dir
, "-POSIX-",
1683 ml_type
, "-Type-", "-Flags-");
1687 while ((mnt
= getmntent (0)))
1689 printf ("%-*s %-*s %-*s %s\n",
1690 ml_fsname
, mnt
->mnt_fsname
,
1691 ml_dir
, mnt
->mnt_dir
, ml_type
, mnt
->mnt_type
, mnt
->mnt_opts
);
1697 ("Looking to see where common programs can be found, if at all...\n");
1698 for (i
= 0; common_apps
[i
].name
; i
++)
1699 if (!find_app_on_path ((char *) common_apps
[i
].name
, 1))
1701 if (common_apps
[i
].missing_is_good
)
1702 printf ("Not Found: %s (good!)\n", common_apps
[i
].name
);
1704 printf ("Not Found: %s\n", common_apps
[i
].name
);
1709 printf ("Looking for various Cygwin DLLs... (-v gives version info)\n");
1710 int cygwin_dll_count
= 0;
1711 char cygdll_path
[32768];
1712 for (pathlike
*pth
= paths
; pth
->dir
; pth
++)
1714 WIN32_FIND_DATAW ffinfo
;
1715 sprintf (tmp
, "%s*.*", pth
->dir
);
1716 wide_path
wpath (tmp
);
1717 HANDLE ff
= FindFirstFileW (wpath
, &ffinfo
);
1718 int found
= (ff
!= INVALID_HANDLE_VALUE
);
1719 found_cygwin_dll
= NULL
;
1722 char f
[FILENAME_MAX
+ 1];
1723 wcstombs (f
, ffinfo
.cFileName
, sizeof f
);
1724 if (strcasecmp (f
+ strlen (f
) - 4, ".dll") == 0)
1726 if (strncasecmp (f
, "cyg", 3) == 0)
1728 sprintf (tmp
, "%s%s", pth
->dir
, f
);
1729 if (strcasecmp (f
, "cygwin1.dll") == 0)
1731 if (!cygwin_dll_count
)
1732 strcpy (cygdll_path
, pth
->dir
);
1733 if (!cygwin_dll_count
1734 || strcasecmp (cygdll_path
, pth
->dir
) != 0)
1736 found_cygwin_dll
= strdup (tmp
);
1742 found
= FindNextFileW (ff
, &ffinfo
);
1744 if (found_cygwin_dll
)
1746 ls (found_cygwin_dll
);
1747 free (found_cygwin_dll
);
1752 if (cygwin_dll_count
> 1)
1753 puts ("Warning: There are multiple cygwin1.dlls on your path");
1754 if (!cygwin_dll_count
)
1755 puts ("Warning: cygwin1.dll not found on your path");
1757 dump_dodgy_apps (verbose
);
1760 dump_sysinfo_services ();
1766 HANDLE h
= CreateFileA ("CONIN$", GENERIC_READ
| GENERIC_WRITE
,
1767 FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
1768 OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
1770 if (h
== INVALID_HANDLE_VALUE
|| h
== NULL
)
1771 return (display_error ("check_keys: Opening CONIN$"));
1775 if (!GetConsoleMode (h
, &mode
))
1776 display_error ("check_keys: GetConsoleMode()");
1779 mode
&= ~ENABLE_PROCESSED_INPUT
;
1780 if (!SetConsoleMode (h
, mode
))
1781 display_error ("check_keys: SetConsoleMode()");
1784 fputs ("\nThis key check works only in a console window,", stderr
);
1785 fputs (" _NOT_ in a terminal session!\n", stderr
);
1786 fputs ("Abort with Ctrl+C if in a terminal session.\n\n", stderr
);
1787 fputs ("Press 'q' to exit.\n", stderr
);
1789 INPUT_RECORD in
, prev_in
;
1791 // Drop first <RETURN> key
1792 ReadConsoleInput (h
, &in
, 1, &mode
);
1794 memset (&in
, 0, sizeof in
);
1799 if (!ReadConsoleInput (h
, &in
, 1, &mode
))
1800 display_error ("check_keys: ReadConsoleInput()");
1802 if (!memcmp (&in
, &prev_in
, sizeof in
))
1805 switch (in
.EventType
)
1808 printf ("%s %ux VK: 0x%02x VS: 0x%02x A: 0x%02x CTRL: ",
1809 in
.Event
.KeyEvent
.bKeyDown
? "Pressed " : "Released",
1810 in
.Event
.KeyEvent
.wRepeatCount
,
1811 in
.Event
.KeyEvent
.wVirtualKeyCode
,
1812 in
.Event
.KeyEvent
.wVirtualScanCode
,
1813 (unsigned char) in
.Event
.KeyEvent
.uChar
.AsciiChar
);
1814 fputs (in
.Event
.KeyEvent
.dwControlKeyState
& CAPSLOCK_ON
?
1815 "CL " : "-- ", stdout
);
1816 fputs (in
.Event
.KeyEvent
.dwControlKeyState
& ENHANCED_KEY
?
1817 "EK " : "-- ", stdout
);
1818 fputs (in
.Event
.KeyEvent
.dwControlKeyState
& LEFT_ALT_PRESSED
?
1819 "LA " : "-- ", stdout
);
1820 fputs (in
.Event
.KeyEvent
.dwControlKeyState
& LEFT_CTRL_PRESSED
?
1821 "LC " : "-- ", stdout
);
1822 fputs (in
.Event
.KeyEvent
.dwControlKeyState
& NUMLOCK_ON
?
1823 "NL " : "-- ", stdout
);
1824 fputs (in
.Event
.KeyEvent
.dwControlKeyState
& RIGHT_ALT_PRESSED
?
1825 "RA " : "-- ", stdout
);
1826 fputs (in
.Event
.KeyEvent
.dwControlKeyState
& RIGHT_CTRL_PRESSED
?
1827 "RC " : "-- ", stdout
);
1828 fputs (in
.Event
.KeyEvent
.dwControlKeyState
& SCROLLLOCK_ON
?
1829 "SL " : "-- ", stdout
);
1830 fputs (in
.Event
.KeyEvent
.dwControlKeyState
& SHIFT_PRESSED
?
1831 "SH " : "-- ", stdout
);
1832 fputc ('\n', stdout
);
1839 while (in
.EventType
!= KEY_EVENT
||
1840 in
.Event
.KeyEvent
.bKeyDown
!= FALSE
||
1841 in
.Event
.KeyEvent
.uChar
.AsciiChar
!= 'q');
1847 /* RFC1738 says that these do not need to be escaped. */
1848 static const char safe_chars
[] = "$-_.+!*'(),";
1850 /* the URL to query. */
1851 static const char base_url
[] =
1852 "http://cygwin.com/cgi-bin2/package-grep.cgi?text=1&grep=";
1854 /* Queries Cygwin web site for packages containing files matching a regexp.
1855 Return value is 1 if there was a problem, otherwise 0. */
1857 package_grep (char *search
)
1861 /* Attempt to dynamically load the necessary WinInet API functions so that
1862 cygcheck can still function on older systems without IE. */
1864 if (!(hWinInet
= LoadLibrary ("wininet.dll")))
1866 fputs ("Unable to locate WININET.DLL. This feature requires Microsoft "
1867 "Internet Explorer v3 or later to function.\n", stderr
);
1871 /* InternetCloseHandle is used outside this function so it is declared
1872 global. The rest of these functions are only used here, so declare them
1873 and call GetProcAddress for each of them with the following macro. */
1875 pInternetCloseHandle
= (BOOL (WINAPI
*) (HINTERNET
))
1876 GetProcAddress (hWinInet
, "InternetCloseHandle");
1877 #define make_func_pointer(name, ret, args) ret (WINAPI * p##name) args = \
1878 (ret (WINAPI *) args) GetProcAddress (hWinInet, #name);
1879 make_func_pointer (InternetAttemptConnect
, DWORD
, (DWORD
));
1880 make_func_pointer (InternetOpenA
, HINTERNET
, (LPCSTR
, DWORD
, LPCSTR
, LPCSTR
,
1882 make_func_pointer (InternetOpenUrlA
, HINTERNET
, (HINTERNET
, LPCSTR
, LPCSTR
,
1883 DWORD
, DWORD
, DWORD
));
1884 make_func_pointer (InternetReadFile
, BOOL
, (HINTERNET
, PVOID
, DWORD
, PDWORD
));
1885 make_func_pointer (HttpQueryInfoA
, BOOL
, (HINTERNET
, DWORD
, PVOID
, PDWORD
,
1887 #undef make_func_pointer
1889 if(!pInternetCloseHandle
|| !pInternetAttemptConnect
|| !pInternetOpenA
1890 || !pInternetOpenUrlA
|| !pInternetReadFile
|| !pHttpQueryInfoA
)
1892 fputs ("Unable to load one or more functions from WININET.DLL. This "
1893 "feature requires Microsoft Internet Explorer v3 or later to "
1894 "function.\n", stderr
);
1898 /* construct the actual URL by escaping */
1899 char *url
= (char *) alloca (sizeof (base_url
) + strlen (search
) * 3);
1900 strcpy (url
, base_url
);
1903 for (dest
= &url
[sizeof (base_url
) - 1]; *search
; search
++)
1905 if (isalnum (*search
)
1906 || memchr (safe_chars
, *search
, sizeof (safe_chars
) - 1))
1913 sprintf (dest
, "%02x", (unsigned char) *search
);
1919 /* Connect to the net and open the URL. */
1920 if (pInternetAttemptConnect (0) != ERROR_SUCCESS
)
1922 fputs ("An internet connection is required for this function.\n", stderr
);
1926 /* Initialize WinInet and attempt to fetch our URL. */
1927 HINTERNET hi
= NULL
, hurl
= NULL
;
1928 if (!(hi
= pInternetOpenA ("cygcheck", INTERNET_OPEN_TYPE_PRECONFIG
, NULL
, NULL
, 0)))
1929 return display_internet_error ("InternetOpen() failed", NULL
);
1931 if (!(hurl
= pInternetOpenUrlA (hi
, url
, NULL
, 0, 0, 0)))
1932 return display_internet_error ("unable to contact cygwin.com site, "
1933 "InternetOpenUrl() failed", hi
, NULL
);
1935 /* Check the HTTP response code. */
1936 DWORD rc
= 0, rc_s
= sizeof (DWORD
);
1937 if (!pHttpQueryInfoA (hurl
, HTTP_QUERY_STATUS_CODE
| HTTP_QUERY_FLAG_NUMBER
,
1938 (void *) &rc
, &rc_s
, NULL
))
1939 return display_internet_error ("HttpQueryInfo() failed", hurl
, hi
, NULL
);
1941 if (rc
!= HTTP_STATUS_OK
)
1943 sprintf (buf
, "error retrieving results from cygwin.com site, "
1944 "HTTP status code %lu", rc
);
1945 return display_internet_error (buf
, hurl
, hi
, NULL
);
1948 /* Fetch result and print to stdout. */
1952 if (!pInternetReadFile (hurl
, (void *) buf
, sizeof (buf
), &numread
))
1953 return display_internet_error ("InternetReadFile failed", hurl
, hi
, NULL
);
1955 fwrite ((void *) buf
, (size_t) numread
, 1, stdout
);
1959 pInternetCloseHandle (hurl
);
1960 pInternetCloseHandle (hi
);
1965 usage (FILE * stream
, int status
)
1968 Usage: cygcheck [-v] [-h] PROGRAM\n\
1969 cygcheck -c [-d] [PACKAGE]\n\
1970 cygcheck -s [-r] [-v] [-h]\n\
1972 cygcheck -f FILE [FILE]...\n\
1973 cygcheck -l [PACKAGE]...\n\
1974 cygcheck -p REGEXP\n\
1976 List system information, check installed packages, or query package database.\n\
1978 At least one command option or a PROGRAM is required, as shown above.\n\
1980 PROGRAM list library (DLL) dependencies of PROGRAM\n\
1981 -c, --check-setup show installed version of PACKAGE and verify integrity\n\
1982 (or for all installed packages if none specified)\n\
1983 -d, --dump-only just list packages, do not verify (with -c)\n\
1984 -s, --sysinfo produce diagnostic system information (implies -c -d)\n\
1985 -r, --registry also scan registry for Cygwin settings (with -s)\n\
1986 -k, --keycheck perform a keyboard check session (must be run from a\n\
1987 plain console only, not from a pty/rxvt/xterm)\n\
1988 -f, --find-package find the package to which FILE belongs\n\
1989 -l, --list-package list contents of PACKAGE (or all packages if none given)\n\
1990 -p, --package-query search for REGEXP in the entire cygwin.com package\n\
1991 repository (requires internet connectivity)\n\
1992 -v, --verbose produce more verbose output\n\
1993 -h, --help annotate output with explanatory comments when given\n\
1994 with another command, otherwise print this help\n\
1995 -V, --version print the version of cygcheck and exit\n\
1997 Note: -c, -f, and -l only report on packages that are currently installed. To\n\
1998 search all official Cygwin packages use -p instead. The -p REGEXP matches\n\
1999 package names, descriptions, and names of files/paths within all packages.\n\
2004 struct option longopts
[] = {
2005 {"check-setup", no_argument
, NULL
, 'c'},
2006 {"dump-only", no_argument
, NULL
, 'd'},
2007 {"sysinfo", no_argument
, NULL
, 's'},
2008 {"registry", no_argument
, NULL
, 'r'},
2009 {"verbose", no_argument
, NULL
, 'v'},
2010 {"keycheck", no_argument
, NULL
, 'k'},
2011 {"find-package", no_argument
, NULL
, 'f'},
2012 {"list-package", no_argument
, NULL
, 'l'},
2013 {"package-query", no_argument
, NULL
, 'p'},
2014 {"help", no_argument
, NULL
, 'h'},
2015 {"version", no_argument
, 0, 'V'},
2016 {0, no_argument
, NULL
, 0}
2019 static char opts
[] = "cdsrvkflphV";
2024 const char *v
= strchr (version
, ':');
2034 len
= strchr (v
, ' ') - v
;
2037 cygcheck version %.*s\n\
2038 System Checker for Cygwin\n\
2039 Copyright (C) 1998 - 2008 Red Hat, Inc.\n\
2041 ", len
, v
, __DATE__
);
2047 int n
= 1 + strchr (ev
, '=') - ev
;
2048 char *s
= (char *) malloc (n
+ 1);
2055 unsigned long (*cygwin_internal
) (int, ...);
2059 load_cygwin (int& argc
, char **&argv
)
2063 if (!(h
= LoadLibrary ("cygwin1.dll")))
2065 if ((cygwin_internal
= (DWORD (*) (int, ...)) GetProcAddress (h
, "cygwin_internal")))
2067 char **av
= (char **) cygwin_internal (CW_ARGV
);
2068 if (av
&& ((DWORD
) av
!= (DWORD
) -1))
2070 /* Copy cygwin's idea of the argument list into this Window application. */
2071 for (argc
= 0; av
[argc
]; argc
++)
2073 argv
= (char **) calloc (argc
+ 1, sizeof (char *));
2074 for (char **argvp
= argv
; *av
; av
++)
2075 *argvp
++ = strdup (*av
);
2079 char **envp
= (char **) cygwin_internal (CW_ENVP
);
2080 if (envp
&& ((DWORD
) envp
!= (DWORD
) -1))
2082 /* Store path and revert to this value, otherwise path gets overwritten
2083 by the POSIXy Cygwin variation, which breaks cygcheck.
2084 Another approach would be to use the Cygwin PATH and convert it to
2088 while (*(env
= _environ
))
2090 if (strncmp (*env
, "PATH=", 5) == 0)
2091 path
= strdup (*env
);
2094 for (char **ev
= envp
; *ev
; ev
++)
2095 if (strncmp (*ev
, "PATH=", 5) != 0)
2096 putenv (strdup (*ev
));
2105 main (int argc
, char **argv
)
2109 load_cygwin (argc
, argv
);
2111 /* Need POSIX sorting while parsing args, but don't forget the
2112 user's original environment. */
2113 char *posixly
= getenv ("POSIXLY_CORRECT");
2114 if (posixly
== NULL
)
2115 (void) putenv("POSIXLY_CORRECT=1");
2116 while ((i
= getopt_long (argc
, argv
, opts
, longopts
, NULL
)) != EOF
)
2157 if (posixly
== NULL
)
2158 putenv ("POSIXLY_CORRECT=");
2160 if ((argc
== 0) && !sysinfo
&& !keycheck
&& !check_setup
&& !list_package
)
2168 if ((check_setup
|| sysinfo
|| find_package
|| list_package
|| grep_packages
)
2172 if ((find_package
|| list_package
|| grep_packages
) && check_setup
)
2175 if (dump_only
&& !check_setup
)
2178 if (find_package
+ list_package
+ grep_packages
> 1)
2182 return check_keys ();
2184 return package_grep (*argv
);
2188 /* FIXME: Add help for check_setup and {list,find}_package */
2189 if (argc
>= 1 && givehelp
&& !check_setup
&& !find_package
&& !list_package
)
2191 printf("Here is where the OS will find your program%s, and which dlls\n",
2192 argc
> 1 ? "s" : "");
2193 printf ("will be used for it. Use -v to see DLL version info\n");
2200 dump_setup (verbose
, argv
, !dump_only
);
2201 else if (find_package
)
2202 package_find (verbose
, argv
);
2203 else if (list_package
)
2204 package_list (verbose
, argv
);
2206 for (i
= 0; i
< argc
; i
++)
2210 ok
&= cygcheck (argv
[i
]);
2219 dump_setup (verbose
, NULL
, false);
2223 puts ("Use -h to see help about each section");
2226 return ok
? EXIT_SUCCESS
: EXIT_FAILURE
;