Hi Colin, hi Nate, Colin Watson wrote on Thu, Apr 19, 2018 at 10:06:28AM +0100:
> "man ./apropos.1", as Nate pointed out. man-db's heuristic is that if > the page name contains a slash then it's surely a path name instead and > should be treated as such; I think that's a reasonable one. Thank you for explaining the heuristic and for pointing out the missing feature in mandoc. Given the existence of the -l option, having the heuristic is maybe not absolutely required, but i agree that it is not unreasonable, and we have seen that the absence of the heuristic can confuse casual users who are used to man-db. So with the commit below, i added the same heuristic to mandoc. Even mixing page names and file names on the command line now works: $ man -w man ./man.1 apropos ./apropos.1 /usr/share/man/man1/apropos.1 /usr/share/man/man1/man.1 /usr/share/man/man7/man.7 ./man.1 ./apropos.1 By the way, the old version of man-db in jessie exhibits a strange behaviour in that case, but probably that has been fixed long ago: $ lsb_release -d Description: Debian GNU/Linux 8.10 (jessie) $ dpkg-query -l man-db | tail -n 1 ii man-db 2.7.0.2-5 i386 on-line manual pager $ man --version man 2.7.0.2 $ man -w man ./man.1 man: man-./man.1: No such file or directory man: man_./man.1: No such file or directory /usr/share/man/man1/man.1.gz ./man.1 Yours, Ingo Log Message: ----------- Compatibility with man-db: In page name mode (= man(1) default mode), also try to interpret names containing slashes as absolute or relative file names. Missing feature reported by Nate Bargmann on <groff at gnu dot org>, and the man-db maintainer Colin Watson <cjwatson at debian dot org> kindly explained to me how this is supposed to work. Modified Files: -------------- mandoc: main.c Revision Data ------------- Index: main.c =================================================================== RCS file: /home/cvs/mandoc/mandoc/main.c,v retrieving revision 1.304 retrieving revision 1.305 diff -Lmain.c -Lmain.c -u -p -r1.304 -r1.305 --- main.c +++ main.c @@ -132,7 +132,7 @@ main(int argc, char *argv[]) size_t i, sz; int prio, best_prio; enum outmode outmode; - int fd; + int fd, startdir; int show_usage; int options; int use_pager; @@ -386,15 +386,34 @@ main(int argc, char *argv[]) argc, argv, &res, &sz)) usage(search.argmode); - if (sz == 0) { - if (search.argmode == ARG_NAME) - fs_search(&search, &conf.manpath, - argc, argv, &res, &sz); - else - warnx("nothing appropriate"); + if (sz == 0 && search.argmode == ARG_NAME) + fs_search(&search, &conf.manpath, + argc, argv, &res, &sz); + + if (search.argmode == ARG_NAME) { + for (c = 0; c < argc; c++) { + if (strchr(argv[c], '/') == NULL) + continue; + if (access(argv[c], R_OK) == -1) { + warn("%s", argv[c]); + continue; + } + res = mandoc_reallocarray(res, + sz + 1, sizeof(*res)); + res[sz].file = mandoc_strdup(argv[c]); + res[sz].names = NULL; + res[sz].output = NULL; + res[sz].ipath = SIZE_MAX; + res[sz].bits = 0; + res[sz].sec = 10; + res[sz].form = FORM_SRC; + sz++; + } } if (sz == 0) { + if (search.argmode != ARG_NAME) + warnx("nothing appropriate"); rc = MANDOCLEVEL_BADARG; goto out; } @@ -478,7 +497,29 @@ main(int argc, char *argv[]) parse(&curp, STDIN_FILENO, "<stdin>"); } + /* + * Remember the original working directory, if possible. + * This will be needed if some names on the command line + * are page names and some are relative file names. + * Do not error out if the current directory is not + * readable: Maybe it won't be needed after all. + */ + startdir = open(".", O_RDONLY | O_DIRECTORY); + while (argc > 0) { + + /* + * Changing directories is not needed in ARG_FILE mode. + * Do it on a best-effort basis. Even in case of + * failure, some functionality may still work. + */ + if (resp != NULL) { + if (resp->ipath != SIZE_MAX) + (void)chdir(conf.manpath.paths[resp->ipath]); + else if (startdir != -1) + (void)fchdir(startdir); + } + fd = mparse_open(curp.mp, resp != NULL ? resp->file : *argv); if (fd != -1) { if (use_pager) { @@ -488,11 +529,9 @@ main(int argc, char *argv[]) if (resp == NULL) parse(&curp, fd, *argv); - else if (resp->form == FORM_SRC) { - /* For .so only; ignore failure. */ - (void)chdir(conf.manpath.paths[resp->ipath]); + else if (resp->form == FORM_SRC) parse(&curp, fd, resp->file); - } else + else passthrough(resp->file, fd, conf.output.synopsisonly); @@ -525,6 +564,10 @@ main(int argc, char *argv[]) if (--argc) mparse_reset(curp.mp); } + if (startdir != -1) { + (void)fchdir(startdir); + close(startdir); + } if (curp.outdata != NULL) { switch (curp.outtype) { @@ -745,7 +788,8 @@ fs_search(const struct mansearch *cfg, c cfg->firstmatch) return 1; } - if (res != NULL && *ressz == lastsz) + if (res != NULL && *ressz == lastsz && + strchr(*argv, '/') == NULL) warnx("No entry for %s in the manual.", *argv); lastsz = *ressz; argv++;