diff options
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | src/tests/Makefile.am | 1 | ||||
-rw-r--r-- | src/tests/Makefile.in | 1 | ||||
-rwxr-xr-x | src/tests/whatis-1 | 58 | ||||
-rw-r--r-- | src/whatis.c | 118 |
6 files changed, 169 insertions, 26 deletions
@@ -1,3 +1,16 @@ +Mon Feb 27 13:26:47 GMT 2012 Colin Watson <cjwatson@debian.org> + + * src/whatis.c (main): Move locale manpath expansion to ... + (locale_manpath): ... here (new function). + (suitable_manpath): New function. + (do_whatis): If a page contains a slash and is a path to an + executable on $PATH, then look up its base name only in + appropriate manual hierarchies. + (search): Pass current manpath entry to do_whatis. + * src/tests/whatis-1: New file. + * src/tests/Makefile.am (ALL_TESTS): Add whatis-1. + * NEWS: Document this. + Wed Feb 22 03:04:45 GMT 2012 Colin Watson <cjwatson@debian.org> Optimise apropos when given many arguments (Ubuntu bug #927028). @@ -8,6 +8,10 @@ Major changes since man-db 2.6.1: o apropos is much faster when run with many arguments. + o whatis may be given the full path to an executable as an argument, + in which case it will look up the base name of that executable in + the appropriate parts of the manpath. + man-db 2.6.1 (14 February 2012) =============================== diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am index b7560426..6090f631 100644 --- a/src/tests/Makefile.am +++ b/src/tests/Makefile.am @@ -26,6 +26,7 @@ ALL_TESTS = \ man-1 man-2 man-3 \ manconv-1 manconv-2 manconv-3 \ mandb-1 mandb-2 mandb-3 mandb-4 mandb-5 mandb-6 \ + whatis-1 \ zsoelim-1 if !CROSS_COMPILING TESTS = $(ALL_TESTS) diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in index 76fae660..448e1195 100644 --- a/src/tests/Makefile.in +++ b/src/tests/Makefile.in @@ -1145,6 +1145,7 @@ ALL_TESTS = \ man-1 man-2 man-3 \ manconv-1 manconv-2 manconv-3 \ mandb-1 mandb-2 mandb-3 mandb-4 mandb-5 mandb-6 \ + whatis-1 \ zsoelim-1 @CROSS_COMPILING_FALSE@TESTS = $(ALL_TESTS) diff --git a/src/tests/whatis-1 b/src/tests/whatis-1 new file mode 100755 index 00000000..22fe468a --- /dev/null +++ b/src/tests/whatis-1 @@ -0,0 +1,58 @@ +#! /bin/sh + +# Test that whatis behaves appropriately when given a path to an executable. + +: ${srcdir=.} +. "$srcdir/testlib.sh" + +: ${MANDB=mandb} +: ${WHATIS=whatis} + +init +fake_config /usr/share/man /usr/local/man +cat >>"$tmpdir/manpath.config" <<EOF +MANPATH_MAP $tmpdir/usr/bin $tmpdir/usr/share/man +MANPATH_MAP $tmpdir/usr/local/bin $tmpdir/usr/local/man +EOF + +write_page test 1 "$tmpdir/usr/share/man/man1/test.1.gz" \ + UTF-8 gz '' 'test \- /usr/bin/test' +write_page test 8 "$tmpdir/usr/local/man/man8/test.8.gz" \ + UTF-8 gz '' 'test \- /usr/local/bin/test' +mkdir -p "$tmpdir/usr/bin" "$tmpdir/usr/local/bin" +touch "$tmpdir/usr/bin/test" "$tmpdir/usr/local/bin/test" +chmod +x "$tmpdir/usr/bin/test" "$tmpdir/usr/local/bin/test" +MANPATH="$tmpdir/usr/share/man:$tmpdir/usr/local/man" run $MANDB \ + -C "$tmpdir/manpath.config" -u -q \ + "$tmpdir/usr/share/man:$tmpdir/usr/local/man" + +cat >"$tmpdir/1.exp" <<EOF +test (1) - /usr/bin/test +test (8) - /usr/local/bin/test +EOF +PATH="$PATH:$tmpdir/usr/bin:$tmpdir/usr/local/bin" \ + MANPATH="$tmpdir/usr/share/man:$tmpdir/usr/local/man" run $WHATIS \ + -C "$tmpdir/manpath.config" test >"$tmpdir/1.out" +expect_pass 'simple name returns all matches' \ + 'diff -u "$tmpdir/1.exp" "$tmpdir/1.out"' + +cat >"$tmpdir/2.exp" <<EOF +test (1) - /usr/bin/test +EOF +PATH="$PATH:$tmpdir/usr/bin:$tmpdir/usr/local/bin" \ + MANPATH="$tmpdir/usr/share/man:$tmpdir/usr/local/man" run $WHATIS \ + -C "$tmpdir/manpath.config" "$tmpdir/usr/bin/test" >"$tmpdir/2.out" +expect_pass '/usr/bin/test only returns appropriate match' \ + 'diff -u "$tmpdir/2.exp" "$tmpdir/2.out"' + +cat >"$tmpdir/3.exp" <<EOF +test (8) - /usr/local/bin/test +EOF +PATH="$PATH:$tmpdir/usr/bin:$tmpdir/usr/local/bin" \ + MANPATH="$tmpdir/usr/share/man:$tmpdir/usr/local/man" run $WHATIS \ + -C "$tmpdir/manpath.config" "$tmpdir/usr/local/bin/test" \ + >"$tmpdir/3.out" +expect_pass '/usr/local/bin/test only returns appropriate match' \ + 'diff -u "$tmpdir/3.exp" "$tmpdir/3.out"' + +finish diff --git a/src/whatis.c b/src/whatis.c index 98371417..4c281e6d 100644 --- a/src/whatis.c +++ b/src/whatis.c @@ -51,6 +51,7 @@ #endif /* HAVE_ICONV */ #include <sys/types.h> +#include <sys/stat.h> #include "regex.h" #include "argp.h" @@ -63,6 +64,7 @@ #include "cleanup.h" #include "error.h" #include "pipeline.h" +#include "pathsearch.h" #include "linelength.h" #include "hashtable.h" #include "lower.h" @@ -106,6 +108,7 @@ static char **sections; static char *manp = NULL; static const char *alt_systems = ""; static const char *locale = NULL; +static char *multiple_locale = NULL, *internal_locale; static struct hashtable *apropos_seen = NULL; static struct hashtable *display_seen = NULL; @@ -239,6 +242,30 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) static struct argp apropos_argp = { options, parse_opt, args_doc, apropos_doc }; static struct argp whatis_argp = { options, parse_opt, args_doc }; +static char *locale_manpath (char *manpath) +{ + char *all_locales; + char *new_manpath; + + if (multiple_locale && *multiple_locale) { + if (internal_locale && *internal_locale) + all_locales = xasprintf ("%s:%s", multiple_locale, + internal_locale); + else + all_locales = xstrdup (multiple_locale); + } else { + if (internal_locale && *internal_locale) + all_locales = xstrdup (internal_locale); + else + all_locales = NULL; + } + + new_manpath = add_nls_manpaths (manpath, all_locales); + free (all_locales); + + return new_manpath; +} + #ifdef HAVE_ICONV static char *simple_convert (iconv_t conv, char *string) { @@ -472,22 +499,80 @@ static inline int do_whatis_section (const char *page, const char *section) return count; } -static void do_whatis (const char * const *pages, int num_pages, int *found) +static int suitable_manpath (const char *manpath, const char *page_dir) +{ + char *page_manp; + char *page_manpathlist[MAXDIRS], **mp; + int ret; + + page_manp = get_manpath_from_path (page_dir, 0); + if (!page_manp || !*page_manp) { + free (page_manp); + return 0; + } + page_manp = locale_manpath (page_manp); + create_pathlist (page_manp, page_manpathlist); + + ret = 0; + for (mp = page_manpathlist; *mp; ++mp) { + if (STREQ (*mp, manpath)) { + ret = 1; + break; + } + } + + for (mp = page_manpathlist; *mp; ++mp) + free (*mp); + free (page_manp); + return ret; +} + +static void do_whatis (const char * const *pages, int num_pages, + const char *manpath, int *found) { int i; for (i = 0; i < num_pages; ++i) { + char *page = xstrdup (pages[i]); + struct stat st; + + if (strchr (page, '/') && stat (page, &st) == 0 && + !S_ISDIR (st.st_mode) && + st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { + /* Perhaps an executable. If its directory is on + * $PATH, then we only want to process this page for + * matching manual hierarchies. + */ + char *page_dir = dir_name (page); + + if (directory_on_path (page_dir)) { + if (suitable_manpath (manpath, page_dir)) { + char *old_page = page; + page = base_name (old_page); + free (old_page); + } else { + debug ("%s not on manpath for %s\n", + manpath, page); + free (page_dir); + continue; + } + } + free (page_dir); + } + if (sections) { char * const *section; for (section = sections; *section; ++section) { - if (do_whatis_section (pages[i], *section)) + if (do_whatis_section (page, *section)) found[i] = 1; } } else { - if (do_whatis_section (pages[i], NULL)) + if (do_whatis_section (page, NULL)) found[i] = 1; } + + free (page); } } @@ -775,7 +860,7 @@ static int search (const char * const *pages, int num_pages) if (regex_opt || wildcard) do_apropos (pages, num_pages, found); else - do_whatis (pages, num_pages, found); + do_whatis (pages, num_pages, *mp, found); } free (database); database = NULL; @@ -799,7 +884,6 @@ static int search (const char * const *pages, int num_pages) int main (int argc, char *argv[]) { - char *multiple_locale = NULL, *internal_locale; #ifdef HAVE_ICONV char *locale_charset; #endif @@ -861,27 +945,9 @@ int main (int argc, char *argv[]) } /* sort out the internal manpath */ - if (manp == NULL) { - char *all_locales; - - if (multiple_locale && *multiple_locale) { - if (internal_locale && *internal_locale) - all_locales = xasprintf ("%s:%s", - multiple_locale, - internal_locale); - else - all_locales = xstrdup (multiple_locale); - } else { - if (internal_locale && *internal_locale) - all_locales = xstrdup (internal_locale); - else - all_locales = NULL; - } - - manp = add_nls_manpaths (get_manpath (alt_systems), - all_locales); - free (all_locales); - } else + if (manp == NULL) + manp = locale_manpath (get_manpath (alt_systems)); + else free (get_manpath (NULL)); create_pathlist (manp, manpathlist); |