* Makefile.in: Link cygcheck with libwininet.a.

* cygcheck.cc: Add includes.
(grep_packages): New global variable.
(display_internet_error): New function.
(safe_chars): New global variable.
(base_url): Ditto.
(package_grep): New function.
(usage): Reword --help output for clarity.  Document new argument.
(longopts): Add 'package-query' option.
(opts): Add 'p' option, reorder to be consistent with 'longopts'.
(main): Accommodate new option.
* utils.sgml (cygcheck): Update --help output.  Document new -p option.
This commit is contained in:
Christopher Faylor 2005-11-22 17:19:17 +00:00
parent 9cd22f86fc
commit a39cfda7ba
5 changed files with 271 additions and 37 deletions

View File

@ -1,3 +1,18 @@
2005-11-22 Brian Dessent <brian@dessent.net>
* Makefile.in: Link cygcheck with libwininet.a.
* cygcheck.cc: Add includes.
(grep_packages): New global variable.
(display_internet_error): New function.
(safe_chars): New global variable.
(base_url): Ditto.
(package_grep): New function.
(usage): Reword --help output for clarity. Document new argument.
(longopts): Add 'package-query' option.
(opts): Add 'p' option, reorder to be consistent with 'longopts'.
(main): Accommodate new option.
* utils.sgml (cygcheck): Update --help output. Document new -p option.
2005-09-22 Corinna Vinschen <corinna@vinschen.de>
Align error message handling to mkpasswd's error messages throughout.
@ -457,9 +472,9 @@
correct system password settings just because the account has admin
privileges.
(usage): Define as "noreturn" function. Restructure and rephrase
output. Accomodate new options.
output. Accommodate new options.
(print_version): Fix copyright dates.
(main): Accomodate new options for setting UF_PASSWD_CANT_CHANGE,
(main): Accommodate new options for setting UF_PASSWD_CANT_CHANGE,
UF_DONT_EXPIRE_PASSWD and UF_PASSWD_NOTREQD settings.
2003-10-17 Christopher Faylor <cgf@redhat.com>

View File

@ -99,15 +99,15 @@ else
$(CXX) $(MINGW_CXXFLAGS) -o $@ ${wordlist 1,2,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS)
endif
cygcheck.exe: cygcheck.o path.o dump_setup.o $(MINGW_DEP_LDLIBS)
cygcheck.exe: cygcheck.o path.o dump_setup.o $(MINGW_DEP_LDLIBS) $(w32api_lib)/libwininet.a
ifeq "$(libz)" ""
@echo '*** Building cygcheck without package content checking due to missing mingw libz.a.'
endif
ifdef VERBOSE
$(CXX) $(MINGW_CXXFLAGS) -o $@ ${wordlist 1,3,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS) $(libz)
$(CXX) $(MINGW_CXXFLAGS) -o $@ ${wordlist 1,3,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS) $(libz) $(w32api_lib)/libwininet.a
else
@echo $(CXX) -o $@ ${wordlist 1,3,$^} ${filter-out -B%, $(MINGW_CXXFLAGS) $(MINGW_LDFLAGS)} $(libz);\
$(CXX) $(MINGW_CXXFLAGS) -o $@ ${wordlist 1,3,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS) $(libz)
@echo $(CXX) -o $@ ${wordlist 1,3,$^} ${filter-out -B%, $(MINGW_CXXFLAGS) $(MINGW_LDFLAGS)} $(libz) $(w32api_lib)/libwininet.a;\
$(CXX) $(MINGW_CXXFLAGS) -o $@ ${wordlist 1,3,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS) $(libz) $(w32api_lib)/libwininet.a
endif
dumper.o: dumper.cc dumper.h

View File

@ -11,11 +11,13 @@
#define cygwin_internal cygwin_internal_dontuse
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <sys/time.h>
#include <ctype.h>
#include <io.h>
#include <windows.h>
#include <wininet.h>
#include "path.h"
#include <getopt.h>
#include "cygwin/include/sys/cygwin.h"
@ -33,6 +35,7 @@ int check_setup = 0;
int dump_only = 0;
int find_package = 0;
int list_package = 0;
int grep_packages = 0;
#ifdef __GNUC__
typedef long long longlong;
@ -124,6 +127,39 @@ display_error (const char *name, bool show_error = true, bool print_failed = tru
return 1;
}
/* Display a WinInet error message, and close a variable number of handles.
(Passed a list of handles terminated by NULL.) */
static int
display_internet_error (const char *message, ...)
{
DWORD err = GetLastError ();
TCHAR err_buf[256];
va_list hptr;
HINTERNET h;
/* in the case of a successful connection but 404 response, there is no
win32 error message, but we still get passed a message to display. */
if (err)
{
if (FormatMessage (FORMAT_MESSAGE_FROM_HMODULE,
GetModuleHandle ("wininet.dll"), err, 0, err_buf,
sizeof (err_buf), NULL) == 0)
strcpy (err_buf, "(Unknown error)");
fprintf (stderr, "cygcheck: %s: %s (win32 error %d)\n", message,
err_buf, err);
}
else
fprintf (stderr, "cygcheck: %s\n", message);
va_start (hptr, message);
while ((h = va_arg (hptr, HINTERNET)) != 0)
InternetCloseHandle (h);
va_end (hptr);
return 1;
}
static void
add_path (char *s, int maxlen)
{
@ -1496,24 +1532,122 @@ check_keys ()
return 0;
}
/* RFC1738 says that these do not need to be escaped. */
static const char safe_chars[] = "$-_.+!*'(),";
/* the URL to query. */
static const char base_url[] =
"http://cygwin.com/cgi-bin2/package-grep.cgi?text=1&grep=";
/* Queries Cygwin web site for packages containing files matching a regexp.
Return value is 1 if there was a problem, otherwise 0. */
static int
package_grep (char *search)
{
char buf[1024];
/* construct the actual URL by escaping */
char *url = (char *) alloca (sizeof (base_url) + strlen (search) * 3);
strcpy (url, base_url);
char *dest;
for (dest = &url[sizeof (base_url) - 1]; *search; search++)
{
if (isalnum (*search)
|| memchr (safe_chars, *search, sizeof (safe_chars) - 1))
{
*dest++ = *search;
}
else
{
*dest++ = '%';
sprintf (dest, "%02x", (unsigned char) *search);
dest += 2;
}
}
*dest = 0;
/* Connect to the net and open the URL. */
if (InternetAttemptConnect (0) != ERROR_SUCCESS)
{
fputs ("An internet connection is required for this function.\n", stderr);
return 1;
}
/* Initialize WinInet and attempt to fetch our URL. */
HINTERNET hi = NULL, hurl = NULL;
if (!(hi = InternetOpen ("cygcheck", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0)))
return display_internet_error ("InternetOpen() failed", NULL);
if (!(hurl = InternetOpenUrl (hi, url, NULL, 0, 0, 0)))
return display_internet_error ("unable to contact cygwin.com site, "
"InternetOpenUrl() failed", hi, NULL);
/* Check the HTTP response code. */
DWORD rc = 0, rc_s = sizeof (DWORD);
if (!HttpQueryInfo (hurl, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,
(void *) &rc, &rc_s, NULL))
return display_internet_error ("HttpQueryInfo() failed", hurl, hi, NULL);
if (rc != HTTP_STATUS_OK)
{
sprintf (buf, "error retrieving results from cygwin.com site, "
"HTTP status code %lu", rc);
return display_internet_error (buf, hurl, hi, NULL);
}
/* Fetch result and print to stdout. */
DWORD numread;
do
{
if (!InternetReadFile (hurl, (void *) buf, sizeof (buf), &numread))
return display_internet_error ("InternetReadFile failed", hurl, hi, NULL);
if (numread)
fwrite ((void *) buf, (size_t) numread, 1, stdout);
}
while (numread);
InternetCloseHandle (hurl);
InternetCloseHandle (hi);
return 0;
}
static void
usage (FILE * stream, int status)
{
fprintf (stream, "\
Usage: cygcheck [OPTIONS] [PROGRAM...]\n\
Check system information or PROGRAM library dependencies\n\
Usage: cygcheck PROGRAM [ -v ] [ -h ]\n\
cygcheck -c [ PACKAGE ] [ -d ]\n\
cygcheck -s [ -r ] [ -v ] [ -h ]\n\
cygcheck -k\n\
cygcheck -f FILE [ FILE ... ]\n\
cygcheck -l [ PACKAGE ] [ PACKAGE ... ]\n\
cygcheck -p REGEXP\n\
List system information, check installed packages, or query package database.\n\
\n\
-c, --check-setup check packages installed via setup.exe\n\
-d, --dump-only no integrity checking of package contents (requires -c)\n\
-s, --sysinfo system information (not with -k)\n\
-v, --verbose verbose output (indented) (for -[cfls] or programs)\n\
-r, --registry registry search (requires -s)\n\
-k, --keycheck perform a keyboard check session (not with -[scfl])\n\
-f, --find-package find installed packages containing files (not with -[cl])\n\
-l, --list-package list the contents of installed packages (not with -[cf])\n\
-h, --help give help about the info (not with -[cfl])\n\
-V, --version output version information and exit\n\
You must at least give either -s or -k or a program name\n");
At least one command option or a PROGRAM is required, as shown above.\n\
\n\
PROGRAM list library (DLL) dependencies of PROGRAM\n\
-c, --check-setup show installed version of PACKAGE and verify integrity\n\
(or for all installed packages if none specified)\n\
-d, --dump-only just list packages, do not verify (with -c)\n\
-s, --sysinfo produce diagnostic system information (implies -c -d)\n\
-r, --registry also scan registry for Cygwin settings (with -s)\n\
-k, --keycheck perform a keyboard check session (must be run from a\n\
plain console only, not from a pty/rxvt/xterm)\n\
-f, --find-package find the package that FILE belongs to\n\
-l, --list-package list contents of PACKAGE (or all packages if none given)\n\
-p, --package-query search for REGEXP in the entire cygwin.com package\n\
repository (requies internet connectivity)\n\
-v, --verbose produce more verbose output\n\
-h, --help annotate output with explanatory comments when given\n\
with another command, otherwise print this help\n\
-V, --version print the version of cygcheck and exit\n\
\n\
Note: -c, -f, and -l only report on packages that are currently installed. To\n\
search all official Cygwin packages use -p instead. The -p REGEXP matches\n\
package names, descriptions, and names of files/paths within all packages.\n\
\n");
exit (status);
}
@ -1526,12 +1660,13 @@ struct option longopts[] = {
{"keycheck", no_argument, NULL, 'k'},
{"find-package", no_argument, NULL, 'f'},
{"list-package", no_argument, NULL, 'l'},
{"package-query", no_argument, NULL, 'p'},
{"help", no_argument, NULL, 'h'},
{"version", no_argument, 0, 'V'},
{0, no_argument, NULL, 0}
};
static char opts[] = "cdfhklrsvV";
static char opts[] = "cdsrvkflphV";
static void
print_version ()
@ -1643,6 +1778,9 @@ main (int argc, char **argv)
case 'l':
list_package = 1;
break;
case 'p':
grep_packages = 1;
break;
case 'h':
givehelp = 1;
break;
@ -1661,20 +1799,23 @@ main (int argc, char **argv)
else
usage (stderr, 1);
if ((check_setup || sysinfo || find_package || list_package) && keycheck)
if ((check_setup || sysinfo || find_package || list_package || grep_packages)
&& keycheck)
usage (stderr, 1);
if ((find_package || list_package) && check_setup)
if ((find_package || list_package || grep_packages) && check_setup)
usage (stderr, 1);
if (dump_only && !check_setup)
usage (stderr, 1);
if (find_package && list_package)
if (find_package + list_package + grep_packages > 1)
usage (stderr, 1);
if (keycheck)
return check_keys ();
if (grep_packages)
return package_grep (*argv);
init_paths ();

View File

@ -379,6 +379,7 @@ dowin (char option)
GetWindowsDirectory (buf, MAX_PATH);
strcat (buf, "\\Profiles");
}
fprintf (stderr, "************** buf %s\n", buf);
break;
case 'S':

View File

@ -13,19 +13,37 @@ command-line utilities support the <literal>--help</literal> and
<sect2 id="cygcheck"><title>cygcheck</title>
<screen>
Usage: cygcheck [OPTIONS] [PROGRAM...]
Check system information or PROGRAM library dependencies
Usage: cygcheck PROGRAM [ -v ] [ -h ]
cygcheck -c [ PACKAGE ... ] [ -d ]
cygcheck -s [ -r ] [ -v ] [ -h ]
cygcheck -k
cygcheck -f FILE [ FILE ... ]
cygcheck -l [ PACKAGE ... ]
cygcheck -p REGEXP
List system information, check installed packages, or query package database.
-c, --check-setup check packages installed via setup.exe
-d, --dump-only no integrity checking of package contents (requires -c)
-s, --sysinfo system information (not with -k)
-v, --verbose verbose output (indented) (for -[cfls] or programs)
-r, --registry registry search (requires -s)
-k, --keycheck perform a keyboard check session (not with -[scfl])
-f, --find-package find installed packages containing files (not with -[cl])
-l, --list-package list the contents of installed packages (not with -[cf])
-h, --help give help about the info (not with -[cfl])
-V, --version output version information and exit
At least one command option or a PROGRAM is required, as shown above.
PROGRAM list library (DLL) dependencies of PROGRAM
-c, --check-setup show installed version of PACKAGE and verify integrity
(or for all installed packages if none specified)
-d, --dump-only just list packages, do not verify (with -c)
-s, --sysinfo produce diagnostic system information (implies -c -d)
-r, --registry also scan registry for Cygwin settings (with -s)
-k, --keycheck perform a keyboard check session (must be run from a
plain console only, not from a pty/rxvt/xterm)
-f, --find-package find the package that FILE belongs to
-l, --list-package list contents of PACKAGE (or all packages if none given)
-p, --package-query search for REGEXP in the entire cygwin.com package
repository (requies internet connectivity)
-v, --verbose produce more verbose output
-h, --help annotate output with explanatory comments when given
with another command, otherwise print this help
-V, --version print the version of cygcheck and exit
Note: -c, -f, and -l only report on packages that are currently installed. To
search all official Cygwin packages use -p instead. The -p REGEXP matches
package names, descriptions, and names of files/paths within all packages.
</screen>
<para>
@ -65,10 +83,10 @@ For example, to find out about <filename>/usr/bin/less</filename> and its
package:
<example><title>Example <command>cygcheck</command> usage</title>
<screen>
$ cygcheck.exe -f /usr/bin/less
$ cygcheck -f /usr/bin/less
less-381-1
$ cygcheck.exe -l less
$ cygcheck -l less
/usr/bin/less.exe
/usr/bin/lessecho.exe
/usr/bin/lesskey.exe
@ -98,6 +116,65 @@ ones that have "Cygwin" in the name. If you are paranoid about
privacy, you may remove information from this report, but please keep
in mind that doing so makes it harder to diagnose your problems.</para>
<para>In contrast to the other options that search the packages that are
installed on your local system, the <literal>-p</literal> option can be used
to search the entire official Cygwin package repository. It takes as argument
a Perl-compatible regular expression which is used to match package names,
package descriptions, and path/filenames of the contents of packages. This
feature requires an active internet connection, since it must query the
<literal>cygwin.com</literal> web site. In fact, it is equalivant to the
search that is available on the <ulink url="http://cygwin.com/packages/">Cygwin
package listing</ulink> page.</para>
<para>For example, perhaps you are getting an error because you are missing a
certain DLL and you want to know which package includes that file:
<example><title>Searching all packages for a file</title>
<screen>
$ cygcheck -p 'cygintl-2\.dll'
Found 1 matches for 'cygintl-2\.dll'.
libintl2-0.12.1-3 GNU Internationalization runtime library
$ cygcheck -p 'libexpat.*\.a'
Found 2 matches for 'libexpat.*\.a'.
expat-1.95.7-1 XML parser library written in C
expat-1.95.8-1 XML parser library written in C
$ cygcheck -p '/ls\.exe'
Found 2 matches for '/ls\.exe'.
coreutils-5.2.1-5 GNU core utilities (includes fileutils, sh-utils and textutils)
coreutils-5.3.0-6 GNU core utilities (includes fileutils, sh-utils and textutils)
</screen>
</example>
</para>
<para>Note that this option takes a regular expression, not a glob or wildcard.
This means that you need to use <literal>.*</literal> if you want something
similar to the wildcard <literal>*</literal> commonly used in filename globbing.
Similarly, to match the period character you should use <literal>\.</literal>
since the <literal>.</literal> character in a regexp is a metacharacter that
will match any character. Also be aware that the characters such as
<literal>\</literal> and <literal>*</literal> are shell metacharacters, so
they must be either escaped or quoted, as in the example above.</para>
<para>The third example above illustrates that if you want to match a whole
filename, you should include the <literal>/</literal> path seperator. In the
given example this ensures that filenames that happen to end in
<literal>ls.exe</literal> such as <literal>ncftpls.exe</literal> are not shown.
Note that this use does not mean "look for packages with <literal>ls</literal>
in the root directory," since the <literal>/</literal> can match anywhere in the
path. It's just there to anchor the match so that it matches a full
filename.</para>
<para>By default the matching is case-sensitive. To get a case insensitive
match, begin your regexp with <literal>(?i)</literal> which is a PCRE-specific
feature. For complete documentation on Perl-compatible regular expression
syntax and options, read the <command>perlre</command> manpage, or one of many
websites such as <literal>perldoc.com</literal> that document the Perl
language.</para>
<para>The <command>cygcheck</command> program should be used to send
information about your system for troubleshooting when requested.
When asked to run this command save the output so that you can email it,