groff
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [groff] groff as the basis for comprehensive documentation?


From: Ingo Schwarze
Subject: Re: [groff] groff as the basis for comprehensive documentation?
Date: Thu, 19 Apr 2018 18:48:19 +0200
User-agent: Mutt/1.8.0 (2017-02-23)

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++;



reply via email to

[Prev in Thread] Current Thread [Next in Thread]